3

我正在使用新的异步等待功能从 C# 中的后台工作人员升级。在下面的代码中,我尝试使用 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 块中的错误。我错过了什么?

4

3 回答 3

4

如果这是在 UI 事件处理程序中运行,您可以将async修改器添加到方法签名并更改t1.Wait()await t1. 这会将控制权返回给 UI 线程,并且当 Thread.Sleep 完成时,将执行延续并捕获任何异常。

于 2013-10-06T08:29:23.713 回答
3

当您使用 时Task.Wait(),您基本上是在说“在这里等待我的任务完成”。这就是你阻塞线程的原因。在任务中处理异常的一个好方法是使用Task.ContinueWith重载和传递,OnlyOnFaulted如下TaskContinuationOption所示:

Task yourTask = new Task {...};
yourTask.ContinueWith( t=> { /*handle expected exceptions*/ }, TaskContinuationOptions.OnlyOnFaulted );
于 2013-10-06T07:37:23.423 回答
3

如果您打算使用基于任务的异步模式,那么您应该使用推荐的指南。我有一篇MSDN 文章描述了其中的许多。

尤其是:

  • 用.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);
}  
于 2013-10-06T12:34:05.360 回答