【问题标题】:Does the Recommended Task Exception-Handling Code Synchronize the Task?推荐的任务异常处理代码是否同步任务?
【发布时间】:2013-01-07 11:26:11
【问题描述】:

看起来 MSDN 上用于处理任务中引发的异常的模式会同步代码。这是来自MSDN page的代码:

var task1 = Task.Factory.StartNew(() =>
{
    throw new MyCustomException("I'm bad, but not too bad!");
});    
try
{
    task1.Wait();
}
catch (AggregateException ae)
{
    // Code removed
}

调用task1.Wait(); 会导致调用线程阻塞,直到task1 完成,对吗?如果是这样,那么我根本看不到使用 Task 的理由,因为无论是使用 Task 同步调用还是异步调用代码,调用线程都会阻塞,直到代码完成运行或抛出异常。

另外,如果 task1 在调用代码进入 try-catch 块之前抛出异常会发生什么?如果可能,try-catch 块将不会捕获 AggregateException。

如果我希望调用线程被通知任务中引发的异常,我应该怎么做?我认为我不应该打电话给task1.Wait(); 才能收到异常通知。我知道ContinueWith(),但ContinueWith() 中的代码也在单独的线程中运行,而不是在调用线程中。

【问题讨论】:

    标签: c# multithreading exception-handling task-parallel-library


    【解决方案1】:

    调用task1.Wait();导致调用线程阻塞,直到 task1 完成,对吧?如果是这样,那么我看不到使用任务的理由 全部,因为代码是同步调用还是 异步使用任务,调用线程将阻塞,直到 要么代码运行完毕,要么抛出异常。

    没错。但是您可以在调用Wait() 方法之前在调用线程上做任何您需要的事情(例如启动其他任务或执行某些操作)。

    另外,如果 task1 在 调用代码进入 try-catch 块?如果可以的话, try-catch 块不会捕获 AggregateException。

    异常将被捕获并在内部存储。然后,当您在任务实例上调用Wait() 方法时,原始异常将被包装在AggregateException 中并传播到调用线程。

    【讨论】:

    • 如果我的task1 是一个长时间运行的任务,或者运行该任务的时间量是不确定的,我将不知道我需要多少行代码来适应我的尝试捕获块。我正在寻找更强大的解决方案。如果我可以将事件处理程序连接到仅在发生异常时运行的任务,那将起作用。我可以用 BackgroundWorker 做这样的事情,但我想使用 Task。
    • @user1214135 你在找ContinueWith()吗?
    • @user1214135 您可以使用ContinueWith() 设置延续(正如@svick 建议的那样),检查Task.IsFaulted/Task.Exception 属性,例如,做某事(显示错误消息?) UI 线程使用Control.Invoke() 方法。
    • @user1214135 或者,根据您的需要,您可能更喜欢使用SynchronizationContext 或其他东西而不是Control.Invoke
    • 正如我所提到的,我不能使用ContinueWith(),因为它也在单独的线程上运行。我不能使用Control.Invoke,因为我的调用线程不是 GUI 线程(我实际上使用的是控制台程序)。我尝试使用SynchronizationContext,但SynchronizationContext.Current 对我来说是空的。我尝试创建一个SynchronizationContext,但也许我做错了。当我将它传递给任务然后发布SendOrPostCallback 时,它在第三个线程上运行:ManagedThreadIds 都是不同的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 2019-08-20
    • 2012-02-04
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    相关资源
    最近更新 更多