RX_*_*_RX 7 .net c# task-parallel-library async-await
假设我有以下代码:
private static void Run()
{
TaskScheduler.UnobservedTaskException += delegate { Console.WriteLine("Unobserved task exception!"); };
try
{
RunAsync().Wait();
}
catch (Exception)
{
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Thread.Sleep(Timeout.InfiniteTimeSpan);
}
private static async Task RunAsync()
{
var task1 = ThrowAsync();
var task2 = ThrowAsync();
await task1;
await task2;
}
private static async Task ThrowAsync()
{
throw new Exception("Test exception");
}
Run Code Online (Sandbox Code Playgroud)
此代码输出,Unobserved task exception!因为task2未观察到异常.
我的问题如下:有没有办法以编程方式确定哪个任务有未观察到的异常?例如,我想获取一个调用任务或类似的方法的堆栈跟踪:
Unobserved exception: task2 in RunAsync()
Run Code Online (Sandbox Code Playgroud)
遗憾的是,异常堆栈跟踪是不够的.上面的代码只是一个演示,在实际的应用程序中,我有时会有一些未观察到的任务异常,其堆栈跟踪如下:
System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.HttpApplication.get_CurrentModuleContainer()
at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
Run Code Online (Sandbox Code Playgroud)
人们将能够判断哪个任务实例有未观察到的异常。那将在task2第二个下await
await task1;
await task2;
Run Code Online (Sandbox Code Playgroud)
因为第一个await“观察”的结果task1。
TaskScheduler.UnobservedTaskException然后,如果事件处理程序被修改为呈现提供的实际任务异常
TaskScheduler.UnobservedTaskException += delegate(object o, UnobservedTaskExceptionEventArgs ea)
{
Console.WriteLine($"Unobserved task exception! {ea.Exception.ToString()}");
};
Run Code Online (Sandbox Code Playgroud)
然后可以通过观察异常的堆栈跟踪来跟踪任务代码的失败区域:
Unobserved task exception!
System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Test exception)
---> System.Exception: Test exception
at ConsoleApp1.Program.ThrowAsync() in C:\Users\sergepavlov\Desktop\ConsoleApp1\ConsoleApp1\Program.cs:line 42
--- End of inner exception stack trace ---
---> (Inner Exception #0) System.Exception: Test exception
at ConsoleApp1.Program.ThrowAsync() in C:\Users\sergepavlov\Desktop\ConsoleApp1\ConsoleApp1\Program.cs:line 42
<---
Run Code Online (Sandbox Code Playgroud)
希望这是有道理的。