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处理。我认为问题中代码的目的是返回一个成功的任务
,无论原始任务
是否失败。