处理任务并行库中的异常

Handling Exceptions in Task Parallel library

我从 COLIN Mackay 的博客上的这篇文章中获得了以下代码。 Tasks that throw exceptions 正如本文所建议的那样,任务中抛出的异常不会冒泡,除非调用了 Wait… 方法之一(不包括 WaitAny)。 好吧,我有 2给出两个不同结果的相似场景。

第一个场景

  1. 把下面的部分注释掉(先注释这个)
  2. (评论这一秒)下的部分不评论
  3. 运行 控制台应用程序使用 ctrl+f5 这样调试器就不会在出现异常时中断。
    1. 观察到即使任务抛出异常,除非调用 wait 方法,否则异常不会冒泡。(按 enter 两次调用 wait 方法)

第二种情况

  1. 把下面的部分注释掉(这次评论)
  2. 不评论(先评论这个)下面的部分
  3. 运行 控制台应用程序使用 ctrl+f5 这样调试器就不会在出现异常时中断。
    1. 现在也没有冒泡异常,但不同之处在于任务没有启动,因为控制台不会将任务状态显示为第一种情况,即使两者都抛出异常。 有人可以解释这种行为以及两种异常之间的差异。

这是代码。

using System;
using System.CodeDom;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Threading
{
    class Program
    {
        static void Main(string[] args)
        {
            // Start the tasks
            List<Task> tasks = new List<Task>();
            for (int i = 0; i < 20; i++)
            {
                Task t = Task.Factory.StartNew(PerformTask);
                tasks.Add(t);
            }

            Console.WriteLine("Press enter to display the task status.");
            Console.ReadLine();

            // Display the status of each task.
            // If it has thrown an exception will be "faulted"
            foreach (Task t in tasks)
                Console.WriteLine("Task {0} status: {1}", t.Id, t.Status);

            Console.WriteLine("Press enter to wait for all tasks.");
            Console.ReadLine();

            // This is where the AggregateException is finally thrown
            Task.WaitAll(tasks.ToArray());

            Console.ReadLine();
        }

        public static void PerformTask()
        {
            //comment this first
            //string input = null;
            //string output = input.ToUpper();
            Console.WriteLine("Starting Task {0}", Task.CurrentId);
            //comment this second
            throw new Exception("Throwing exception in task " + Task.CurrentId);
        }
    }
}

the diffrence is that the tasks didnt start as the console doesn't display the status of the task as the first scenario

那是因为第二次,在您的 Console.WriteLine 方法调用之前抛出异常:

string input = null;
string output = input.ToUpper(); // this will throw
Console.WriteLine("Starting Task {0}", Task.CurrentId);

对战:

Console.WriteLine("Starting Task {0}", Task.CurrentId); // This will first be written
throw new Exception("Throwing exception in task " + Task.CurrentId);

如果您想体验相同的行为,请在方法开头写到控制台:

public static void PerformTask()
{
    Console.WriteLine("Starting Task {0}", Task.CurrentId);

    //string input = null;
    //string output = input.ToUpper();

    throw new Exception("Throwing exception in task " + Task.CurrentId);
}