使用任务处理异常

3

假设我有以下代码:

serviceCallFinished = false;
Task.Factory.StartNew(() => {
    response = ServiceManager.GeneralService.ServiceMethod(loginName, password);
}).ContinueWith(parentTask => { serviceCallFinished = true; });

while (!serviceCallFinished)
    Thread.Sleep(100);

if (response.UserValid) { }

在这种情况下,ServiceMethod将抛出一个Exception,但这从未被显示,相反,我会在response.UserValid上得到一个空引用?为什么异常没有传递到我的UI线程?注意:这是在UI线程上进行的,我的想法是不要在服务调用期间阻塞线程。

它并没有回答你的问题,但请移除那个循环以等待完成。使用其他东西(manualResetEvent)。 - Felice Pollano
这里的主线程是一个 UI 线程,不能被阻塞,这就是为什么我使用 Thread.Sleep。我也不想将方法拆分,以便能够将线程发送到特定的方法。 - Banshee
1
如果循环的目的是非阻塞的,那么你肯定是错的:UI线程正在执行睡眠操作而被阻塞。 - Felice Pollano
好的,解决这个问题的唯一方法就是将该方法分割并在ContinueWith中将线程传递到方法的第二部分(method2)。这将涉及很多方法,代码也会变得更加复杂。 - Banshee
Joe的回复是正确等待和异常管理的最佳选择。 - Felice Pollano
4个回答

2

你不需要像那样使用标志来等待异步任务完成。使用Wait()方法即可。

Task t = Task.Factory.StartNew(() => {
    response = ServiceManager.GeneralService.ServiceMethod(loginName, password);
});

try
{
    t.Wait();
}
catch (AggregateException e)
{
   ...
}

Wait() 调用将在整个 AggregateException 中提升任何异常。


是的,就像所写的那样。.Wait有多种重载形式,可以接受时间参数(int毫秒或TimeSpan),并在等待周期内如果任务未完成则返回true或false。http://msdn.microsoft.com/en-us/library/dd270644.aspx - Joe

1

从评论和与发布的示例相反,似乎您想要返回给调用者的逻辑,同时正在等待响应,然后在之后执行一堆操作。 听起来后面的东西包含了许多非常复杂的方法,您希望以过程方式编写它们。 C#团队听到了您的问题以及类似的问题,并开发了async / await框架,将在C# 5中实现。 或者,如果可以的话,这里有一个AsyncCTP可用:http://www.microsoft.com/download/en/details.aspx?id=9983 希望对您有所帮助。


0

看一下 如何处理任务抛出的异常 ,这里还有一个很好的示例。

你可以做的就是用以下代码替换你的睡眠循环:

try
{
    task.Wait();
}
catch (AggregateException ae)
{
  ...
}

0
为什么不像这样写代码呢:
Task.Factory.StartNew(() => 
  {
   response = ServiceManager.GeneralService.ServiceMethod(
     loginName, password);
  })
  .ContinueWith(parentTask => { if (response.UserValid) { } });

看起来更清晰、更响应。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接