2

在 C# WPF 应用程序中,如果在以下按钮单击事件 habdler:

private void start_Click(object sender, RoutedEventArgs e)
{
  for (int i = 2; i < 20; i++)
  {
    var t = Task.Factory.StartNew
    (() =>
         {
            var result=Thread.CurrentThread.ManagedThreadId.ToString();
       //this.Dispatcher.BeginInvoke(new Action(() =>
            textBlock1.Text += "root " + i.ToString() + " " +
            result + Environment.NewLine
       ;//to comment this line if to uncomment th others
       //), null);
          }
     );
  }
}

取消注释注释行,即输出到文本块,Dispatcher.BeginInvoke()然后填充不同的线程ID。

尽管有注释行,如上所示,文本块保持空白并且没有抛出异常。

在类似情况下使用Parallel.For

private void start_Click(object sender, RoutedEventArgs e)
{
  Parallel.For(2, 6, (i) 
     => {
           var result = Thread.CurrentThread.ManagedThreadId.ToString();
           textBlock1.Text += "root " + i.ToString() + " " +
                               result + Environment.NewLine;

         }   );
}

应用程序异常中断:

“调用线程无法访问此对象,因为不同的线程拥有它”

为什么在使用时不会在第一种情况下抛出它Task.Factory.StartNew()
有什么办法可以确保这个例外?

4

1 回答 1

3

任务中抛出的异常总是由任务对象本身处理。例如,当您访问 Task.Result 属性时,稍后会重新引发异常。这样,异常的处理就留给了创建任务的线程。如果您运行第一个代码片段并查看“输出”窗格,您会看到那里记录了多个第一次机会 InvalidOperationException。异常抛出 - 任务只是将它们隐藏起来以便以后重新抛出。

Parallel.For实际上也是如此——它隐藏了委托中发生的所有异常,然后,当循环完成时,它重新抛出在单个AggregateException. 您会注意到调试器在线程调用中中断Parallel.For,而不是在传递给它的委托中。

要使任务中的异常传播到调用线程,就像Parallel.For调用Wait/WaitAll任务一样。

于 2013-04-02T13:38:33.747 回答