处理任务并行库中的异常
Handling Exceptions in Task Parallel library
我从 COLIN Mackay 的博客上的这篇文章中获得了以下代码。
Tasks that throw exceptions 正如本文所建议的那样,任务中抛出的异常不会冒泡,除非调用了 Wait… 方法之一(不包括 WaitAny)。 好吧,我有 2给出两个不同结果的相似场景。
第一个场景
- 把下面的部分注释掉(先注释这个)
- (评论这一秒)下的部分不评论
- 运行 控制台应用程序使用 ctrl+f5 这样调试器就不会在出现异常时中断。
- 观察到即使任务抛出异常,除非调用 wait 方法,否则异常不会冒泡。(按 enter 两次调用 wait 方法)
第二种情况
- 把下面的部分注释掉(这次评论)
- 不评论(先评论这个)下面的部分
- 运行 控制台应用程序使用 ctrl+f5 这样调试器就不会在出现异常时中断。
- 现在也没有冒泡异常,但不同之处在于任务没有启动,因为控制台不会将任务状态显示为第一种情况,即使两者都抛出异常。
有人可以解释这种行为以及两种异常之间的差异。
这是代码。
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);
}
我从 COLIN Mackay 的博客上的这篇文章中获得了以下代码。 Tasks that throw exceptions 正如本文所建议的那样,任务中抛出的异常不会冒泡,除非调用了 Wait… 方法之一(不包括 WaitAny)。 好吧,我有 2给出两个不同结果的相似场景。
第一个场景
- 把下面的部分注释掉(先注释这个)
- (评论这一秒)下的部分不评论
- 运行 控制台应用程序使用 ctrl+f5 这样调试器就不会在出现异常时中断。
- 观察到即使任务抛出异常,除非调用 wait 方法,否则异常不会冒泡。(按 enter 两次调用 wait 方法)
第二种情况
- 把下面的部分注释掉(这次评论)
- 不评论(先评论这个)下面的部分
- 运行 控制台应用程序使用 ctrl+f5 这样调试器就不会在出现异常时中断。
- 现在也没有冒泡异常,但不同之处在于任务没有启动,因为控制台不会将任务状态显示为第一种情况,即使两者都抛出异常。 有人可以解释这种行为以及两种异常之间的差异。
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);
}