我正在使用新的async await功能从C#中的backgroundworker升级。在下面的代码中,我试图用ContinueWith方法复制多个任务的执行。
Task t1 = new Task
(
() =>
{
Thread.Sleep(10000);
// make the Task throw an exception
MessageBox.Show("This is T1");
}
);
Task t2 = t1.ContinueWith
(
(predecessorTask) =>
{
if (predecessorTask.Exception != null)
{
MessageBox.Show("Predecessor Exception within Continuation");
return;
}
Thread.Sleep(1000);
MessageBox.Show("This is Continuation");
},
TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion
);
t1.Start();
try
{
t1.Wait(); <------ Comment
t2.Wait(); <------ Comment
}
catch (AggregateException ex)
{
MessageBox.Show(ex.InnerException.Message);
}
我的问题是当我评论t1.wait和t2.wait时任务没有阻止UI。但是当我取消注释t1.wait和t2.wait UI阻塞直到线程完成。期望的行为是在不阻止UI的情况下捕获try / catch块中的错误。我错过了什么?
答案 0 :(得分:4)
如果这是在UI事件处理程序中运行,则可以将async
修饰符添加到方法签名中,并将t1.Wait()
更改为await t1
。这将返回对UI线程的控制,并且当Thread.Sleep完成时,将继续执行继续,并且将捕获任何异常。
答案 1 :(得分:3)
当你使用Task.Wait()
时,你基本上是在说“等我的任务完成”。这就是你阻止线程的原因。处理任务中的异常的一种好方法是使用Task.ContinueWith
重载并将OnlyOnFaulted
作为TaskContinuationOption
传递,如下所示:
Task yourTask = new Task {...};
yourTask.ContinueWith( t=> { /*handle expected exceptions*/ }, TaskContinuationOptions.OnlyOnFaulted );
答案 2 :(得分:3)
如果您要使用Task-based Asynchronous Pattern,则应使用建议的指南。我有MSDN article描述了其中许多内容。
特别是:
Task.Run
使用Task
代替Task.Start
构造函数。await
代替ContinueWith
。AttachedToParent
。如果您应用这些更改,您的代码将如下所示:
try
{
await Task.Run(() =>
{
Thread.Sleep(10000);
// make the Task throw an exception
MessageBox.Show("This is T1");
});
await Task.Run(() =>
{
Thread.Sleep(1000);
MessageBox.Show("This is Continuation");
});
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}