c# - 查找具有未观察到异常的任务的最佳策略

标签 c# .net async-await task-parallel-library

假设我有以下代码:

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

这段代码输出 Unobserved task exception! 因为 task2 中的异常没有被观察到。

我的问题如下:有没有办法以编程方式确定哪个任务有未观察到的异常?例如,我想获取调用任务或类似这样的方法的堆栈跟踪:

Unobserved exception: task2 in RunAsync()

遗憾的是,异常堆栈跟踪是不够的。上面的代码只是一个演示,在真实世界的应用程序中,我有时会遇到未观察到的任务异常,堆栈跟踪如下:

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)

最佳答案

人们将能够分辨出哪个 Task 实例的异常未被观察到。那将是第二个 await

下的 task2
await task1;
await task2;

因为第一个await“观察”了task1的结果。

然后,如果事件处理程序被修改为呈现 TaskScheduler.UnobservedTaskException 提供的实际任务异常

    TaskScheduler.UnobservedTaskException += delegate(object o, UnobservedTaskExceptionEventArgs ea)
    {
        Console.WriteLine($"Unobserved task exception! {ea.Exception.ToString()}");
    };

然后可以通过观察异常的堆栈跟踪来追踪任务代码的失败区域:

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
<--- 

希望这是有道理的。

关于c# - 查找具有未观察到异常的任务的最佳策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34065942/

相关文章:

c# - CheckedListBox 对接无法正常工作

asp.net - 如何在不切换到 IIS 的情况下将 SSL 证书附加到我的 asp dot net 网站?

c# - 实现返回 Task<T> 的方法的正确方法

javascript - Javascript异步/等待行为说明

c# - DeLeaker 处于远程模式吗?

c# - 添加 WCF 服务会生成 Reference.cs 文件,其中引用 Microsoft.CodeDom 而不是 System.CodeDom

.NET 项目架构

c# - 使用 Visual Basic.NET (VB.NET) 开发的 ASP.NET Core 应用程序可能吗? VS中没有模板

c# - Windows 窗体卡在多个异步任务上

c# - System.Diaganostics.Process.Id 与任务管理器中显示的进程 ID 不同。为什么?