【问题标题】:Best strategy for finding tasks with unobserved exceptions查找具有未观察到异常的任务的最佳策略
【发布时间】:2019-09-10 00:25:24
【问题描述】:

假设我有以下代码:

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_ 对象吗?还是获得更详细的堆栈跟踪就足够了?我不认为你可以做前者;至少我不知道UnobservedTaskException 事件中有什么可以提供这个。但另一方面,如果您想要更多细节,您应该能够查看AggregateException.InnerExceptions 以查看实际异常。请通过更准确地描述您想获得哪些信息而没有获得的信息来改进问题。
  • 我认为这个问题只是意味着他(和我)只是想在我们的代码中找到问题的实际位置。我现在可能有成百上千个任务,在某个地方我有var t = GetSomethingAsync();,但我不知道在哪里

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


【解决方案1】:

人们将能够分辨出哪个 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
<--- 

希望这是有道理的。

【讨论】:

    猜你喜欢
    • 2016-11-25
    • 2013-11-26
    • 1970-01-01
    • 2017-07-27
    • 2011-12-14
    • 1970-01-01
    • 1970-01-01
    • 2012-09-01
    • 2012-02-29
    相关资源
    最近更新 更多