dev*_*ife 34 c# task-parallel-library
我正在阅读一本关于C#任务并行库的书,并且有以下示例,但是永远不会触发TaskScheduler.UnobservedTaskException处理程序.任何人都可以给我任何线索,为什么?
TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) =>
{
eventArgs.SetObserved();
((AggregateException)eventArgs.Exception).Handle(ex =>
{
Console.WriteLine("Exception type: {0}", ex.GetType());
return true;
});
};
Task task1 = new Task(() =>
{
throw new ArgumentNullException();
});
Task task2 = new Task(() => {
throw new ArgumentOutOfRangeException();
});
task1.Start();
task2.Start();
while (!task1.IsCompleted || !task2.IsCompleted)
{
Thread.Sleep( 5000 );
}
Console.WriteLine("done");
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)
Ree*_*sey 53
不幸的是,该示例永远不会向您展示您的代码.该UnobservedTaskException如果一个任务被用一个异常未观测到的GC收集才会发生-只要你坚持一个参考task1和task2时,GC绝不会收集,和你永远不会看到您的异常处理程序.
为了看到实际行为UnobservedTaskException,我会尝试以下(人为的例子):
public static void Main()
{
TaskScheduler.UnobservedTaskException += (object sender, UnobservedTaskExceptionEventArgs eventArgs) =>
{
eventArgs.SetObserved();
((AggregateException)eventArgs.Exception).Handle(ex =>
{
Console.WriteLine("Exception type: {0}", ex.GetType());
return true;
});
};
Task.Factory.StartNew(() =>
{
throw new ArgumentNullException();
});
Task.Factory.StartNew(() =>
{
throw new ArgumentOutOfRangeException();
});
Thread.Sleep(100);
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("Done");
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
这将显示您的消息.第一个Thread.Sleep(100)调用为任务提供了足够的时间.收集和等待强制GC集合,它将激活您的事件处理程序2x.
该示例片段中不会“未观察到”异常。直到垃圾收集器清除任务实例。你必须像这样重写它:
class Program {
static void Main(string[] args) {
TaskScheduler.UnobservedTaskException += ( object sender, UnobservedTaskExceptionEventArgs eventArgs ) =>
{
eventArgs.SetObserved();
( (AggregateException)eventArgs.Exception ).Handle( ex =>
{
Console.WriteLine("Exception type: {0}", ex.GetType());
return true;
} );
};
Run();
GC.Collect();
GC.WaitForPendingFinalizers();
Console.WriteLine("done");
Console.ReadLine();
}
static void Run() {
Task task1 = new Task(() => {
throw new ArgumentNullException();
});
Task task2 = new Task(() => {
throw new ArgumentOutOfRangeException();
});
task1.Start();
task2.Start();
while (!task1.IsCompleted || !task2.IsCompleted) {
Thread.Sleep(50);
}
}
}
Run Code Online (Sandbox Code Playgroud)
不要这样做,请使用 Task.Wait()。