我有一个任务,它使用连接到WCF服务的数据访问库来获取数据。如此布局:
数据访问dll:
using (Service.ServiceClient client = new Service.ServiceClient(EndpointAddress))
{
try
{
//Make my service call
client.close()
//return list
}
catch (FaultException fe)
{
client.Abort();
throw fe;
}
catch (CommunicationException ce)
{
client.Abort();
throw ce;
}
catch (TimeoutException te)
{
client.Abort();
throw te;
}
}
主程序:
Task<List<Stuff>> loadOp = new Task<List<Stuff>>(() => dataAccessDllMethod());
loadOp.Start();
try
{
loadOp.ContinueWith((Sender) =>
{
Sender.Result
}
catch (Exception ex)
{
//Notify User
throw;
}
现在我的代码一直在破坏loadOp的lambda表达式,这意味着用户永远不会收到通知,但从我所读到的内容来看,这是任务中错误处理的正确方法。这是正确的做法,还是有更好的方法?
答案 0 :(得分:1)
当您开始Task
时,在您的情况下Task<List<Stuff>>
,立即取回任务,并承诺将来某个时间完成,并且方法继续执行,这意味着它将完成try
块并退出。它不会阻止或等待Task
完成。你可能会做一些事情:
Task.Result
属性,该属性在阻止该主题时等待Task
的结果。Task.Wait()
,等待Task
完成也阻止线程。await
上的Task
,与之前的两个不同,但会将控制权交还给调用方,直到Task
完成执行 。为了能够做到这一点,编译器生成一个状态机,为我们处理一切。throw
异常以将其传播到调用堆栈,除非有人访问继续Result
的{{1}}或Exception
属性,否则它将无效LI>
醇>
我会做什么而不是为成功或失败创造不同的延续,只需Task
:
await
最后一点,推荐的方法是在创建任务时始终使用Task<List<Stuff>> loadOp = Task.Run<List<Stuff>>(() => dataAccessDllMethod());
try
{
Task<List<Stuff>> loadOp = await Task.Run<List<Stuff>>(() => dataAccessDllMethod());
// do stuff with the result
}
catch (Exception ex)
{
//Notify User
throw;
}
或Task.Run
,以免意外忘记Task.Factory.Startnew
它们并返回永不执行的Start
(使用Cold Task
)
答案 1 :(得分:0)
尝试以下代码我猜您不需要尝试捕获您可以直接编写代码,如下所示..: -
loadOp.ContinueWith((Sender) =>
{
////this will be called on successful completion
Sender.Result
}, TaskContinuationOptions.OnlyOnRanToCompletion);
loadOp.ContinueWith((Sender) =>
{
////Notify user
////This will be called when error occures
Sender.Result
}, TaskContinuationOptions.OnlyOnFaulted);
TaskContinuationOptions枚举的OnlyOnFaulted成员 表示只有在执行时才执行继续 先前的任务引发了异常。