c# - 找出抛出 unobservedTaskException 的位置 : stacktrace is null

标签 c# task-parallel-library .net-4.7

我有一个使用第三方库的大型 C# 应用程序,并且在应用程序的某个位置运行了一个未等待并引发异常的任务。

所以我向 TaskScheduler.UnobservedTaskException 添加了一个事件处理程序:

TaskScheduler.UnobservedTaskException += (sender, args) =>
{
    _logger.Error(args.Exception);
    args.SetObserved();
};

但是,当执行此处理程序时,我收到一些堆栈跟踪为 null 的异常:

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. 
    ---> Grpc.Core.RpcException: Status(StatusCode=Cancelled, Detail="Cancelled")
    --- End of inner exception stack trace ---
---> (Inner Exception #0) Grpc.Core.RpcException: Status(StatusCode=Cancelled, Detail="Cancelled")<---

当我调试这段代码时,args.Exception 的堆栈跟踪为空,我不知道它来自哪里。我尝试使用 Visual Studio 2017 捕获 System.AggregateException 类型的所有异常,但没有捕获到。我 try catch Grpc.Core.RpcException 类型的所有异常,但其中很多都被抛出并仅在用户代码中处理(大约每秒 10 个),而我的未捕获异常每隔几个小时只发生一次,所以它是手动跳过应用程序中抛出的所有数千个 RpcException 是不可行的。

我怎样才能找出这个未捕获的异常发生在哪里?我尝试在所有任务/异步方法中添加 try/catch block ,但无济于事,尽管我可能错过了一些。我尝试从代码中删除所有“即发即弃”任务,但我什至不知道此异常是来 self 的代码还是来自外部代码(在这种情况下,我可以向代码的开发人员报告)。

我的应用程序中未等待的异步方法(async void)发生在事件处理程序中,我尝试放置 try/catch block 来捕获异常。但这个问题仍然存在。

我还能做什么来弄清楚抛出此异常的时间和地点以及未观察到的任务可能在哪里?

最佳答案

要解决此类问题,您可以使用像 dotMemory 这样的内存分析器并收集分配( https://www.jetbrains.com/help/dotmemory/dotMemory_Profiler_Options.html )!

当未处理的异常发生时,拍摄快照,找到任务(可以通过其类型和 ID 来完成)并查看该实例的创建堆栈跟踪 ( https://www.jetbrains.com/help/dotmemory/Creation_Stack_Trace_instance.html )。

这里有一些代码可以帮助您入门:

TaskScheduler.UnobservedTaskException += (sender, args) => 
    MessageBox.Show($"Almost there, now take a snapshot and look for the creation stacktrace of {sender.GetType()}, Id={((Task)sender).Id}!");

希望这对你有用,对我也有用:)

关于c# - 找出抛出 unobservedTaskException 的位置 : stacktrace is null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57769098/

相关文章:

C# 方法返回与 lambda 中的变量

c# - 如何在反序列化 JSON 时在类中定义变量以接收 List<string> 或字符串?

c# - 这种 await/async 的用法是否正确?

c# - 当消费者不堪重负时,如何让快速生产者暂停?

c# - AsParallel() 顺序执行

c# - HttpClient 不使用 ServicePointManager 服务点

c# - 在 UI 线程上调用异步方法

c# -/langversion 的选项 '7.3' 无效;必须是 ISO-1、ISO-2、默认值或 1 到 6 范围内的整数

c# - 验证我的表单

.net - 使用通配符地址时,system.net connectionManagement maxConnection 是每个域还是共享?