C# 任务类-多个等待和异常

C# 任务类-多个等待和异常,c#,.net,multithreading,task-parallel-library,C#,.net,Multithreading,Task Parallel Library,通常,我将任务封装如下: Task t = Task.Factory.StartNew(() => { func_can_throw_exception(); }, token). ContinueWith ((task) => { try { task.Wait(); } catch (Aggrega

通常,我将任务封装如下:

Task t = Task.Factory.StartNew(() =>
    {
        func_can_throw_exception();
    }, token).
ContinueWith
    ((task) =>
        {
            try
            {
                task.Wait();
            }
            catch (AggregateException ae)
            {
                ae.Handle((x) =>
                {
                    //handle
                    return true;
                });
            }
            finally
            {
            }
        });

问题是如果我在一个单独的线程(例如GUI线程)中等待(
t.wait();
)这个任务,会发生什么。这是允许的。如果在任务执行过程中出现异常,该如何处理?

不要这样做。更好的方法是:

Task.Run(() => {
    func_can_throw_exception();
})
.ContinueWith(task => {
    do_something_with(task.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
但是在您提供的代码中,
task.Wait()
不会被阻止,因为
ContinueWith
仅在任务完成后激发


在一般情况下,
task.Wait()
将阻止当前线程,直到任务完成。如果任务失败,则
Wait
将抛出
aggregateeexception
。但是如果不小心,使用
Wait
可能会导致死锁。最好在TPL代码中使用continuations。

在任务上等待通常不是一个好主意,因为它会阻止调用线程,而不是异步等待的
Wait
。阻塞GUI线程尤其危险,因为它会很快导致死锁

您正在内部处理任何异常,因此除非
Handle
引发异常
t。Wait()
不会引发任何异常

您应该使用
async wait

try
{
    await Task.Run(() => func_can_throw_exception());
}
catch (Exception e)
{
    // handle exception
}

他还对已经完成的任务使用了
等待
。他可以简单地使用
TaskContinuationOptions。只有出现故障的
。在这种情况下,
Wait
的调用发生在continuation内部,因此没有阻塞。这只是一种糟糕的形式,因为他可以检查
Faulted
并使用
Handle
,而不是在处理之前重新调用原始异常it@PanagiotisKanavos因为他问起了
t.Wait()并且结果任务名为
t
,而内部任务名为
task
我假设他没有询问内部
Wait()
。特别是当提到GUI线程时。是的。该任务类似于图像捕获线程,其生命周期就是整个程序的生命周期。当用户关闭窗体时,我希望在最终关闭应用程序之前确保所有线程都已完成。@I3arnon没有注意到,这是一种使用任务而不是重新引发异常的奇怪方式,请选中
task.IsFaulted
,然后调用
task.exception.Handle()
。或者使用
async/await
简化整个过程这些线程通常贯穿整个程序生命周期(从相机线程获取图像)。在FormClosed,我想确保在关闭前完成所有任务。我明白了。。。那么我想你确实可以使用
Task.WaitAll
,如果你能额外确保不会出现死锁的话。另外,最好给该函数一个超时时间,这样就不会无限期挂起。如果执行此操作,如果原始的
任务成功,则最终的
任务
(由
ContinueWith()
返回)将被取消。我不认为这样的行为是故意的。@svick我想你说的是
WaitAll
调用-在这种情况下,你肯定是对的,等待应该在原始任务上执行。(使用类似于
var t=Task.Run(…);t.ContinueWith(…);return t;
)@lucastrezesniewski的方法返回失败的
任务
,即使异常(可能)已经由continuation处理。我认为问题中代码的目的是返回一个成功的
任务
,无论原始
任务
是否失败。