且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

TaskScheduler.UnobservedTaskException事件处理程序从未被触发

更新时间:2022-10-18 23:41:10

不幸的是,这个例子绝不会告诉你你的代码。如果一个任务得到由GC收集与异常不可观测的 UnobservedTaskException 只会发生 - 只要你持有到任务1 $ C参$ C>和 TASK2 ,GC将永远不会收集,你永远不会看到您的异常处理程序。



为了看到的 UnobservedTaskException 的行动,我想尝试下面的(人为的例子)的行为:

 公共静态无效的主要()
{
TaskScheduler.UnobservedTaskException + =(对象发件人,EventArgs的UnobservedTaskExceptionEventArgs)=>
{
eventArgs.SetObserved();
((AggregateException)eventArgs.Exception).Handle(EX =>
{
Console.WriteLine(异常类型:{0},ex.GetType());
返回真;
});
};

Task.Factory.StartNew(()=>
{
抛出新的ArgumentNullException();
});

Task.Factory.StartNew(()=>
{
抛出新ArgumentOutOfRangeException();
});


Thread.sleep代码(100);
GC.Collect的();
GC.WaitForPendingFinalizers();

Console.WriteLine(完成);
Console.ReadKey();
}

这将显示您的邮件。第一个 Thread.sleep代码(100)调用提供足够的时间的任务扔。在收集和等待强制GC收集,这将触发事件处理程序2倍。


I'm reading through a book about the C# Task Parallel Library and have the following example but the TaskScheduler.UnobservedTaskException handler is never being triggered. Can anyone give me any clues as to why?

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();

Unfortunately, that example will never show you your code. The UnobservedTaskException will only happen if a Task gets collected by the GC with an exception unobserved - as long as you hold a reference to task1 and task2, the GC will never collect, and you'll never see your exception handler.

In order to see the behavior of the UnobservedTaskException in action, I'd try the following (contrived example):

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();
}

This will show you your messages. The first Thread.Sleep(100) call provides enough time for the tasks to throw. The collect and wait forces a GC collection, which will fire your event handler 2x.