C# 从异步任务中止当前进程

C# 从异步任务中止当前进程,c#,.net,task-parallel-library,windows-error-reporting,C#,.net,Task Parallel Library,Windows Error Reporting,我有一些复杂的函数,它们在通过TPL生成的异步任务中运行,有时会以意外的方式失败。当发生此类故障时,这表示可能导致程序状态损坏的编程错误。因此,我不希望我的程序捕获异常,处理它并“跛行”,我希望我的进程崩溃并终止 我还希望这个东西以这样一种方式消亡:Windows错误报告系统将其检测为崩溃,并执行所有有用的调试工作,如捕获小型转储、将其发送给Microsoft等 我意识到这可能与您关于程序在错误条件下应该做什么的观点背道而驰,但问题不在于此 我遇到的问题是,因为异常是从任务引发的,所以它不会立即

我有一些复杂的函数,它们在通过TPL生成的异步
任务中运行,有时会以意外的方式失败。当发生此类故障时,这表示可能导致程序状态损坏的编程错误。因此,我不希望我的程序捕获异常,处理它并“跛行”,我希望我的进程崩溃并终止

我还希望这个东西以这样一种方式消亡:Windows错误报告系统将其检测为崩溃,并执行所有有用的调试工作,如捕获小型转储、将其发送给Microsoft等

我意识到这可能与您关于程序在错误条件下应该做什么的观点背道而驰,但问题不在于此

我遇到的问题是,因为异常是从任务引发的,所以它不会立即导致进程崩溃。一段时间后,当垃圾收集器明智地决定收集“未观察到的”异常时,它崩溃了

我希望进程立即崩溃,因为

  • 实际错误中的调用堆栈和线程转储是我希望在崩溃转储中收集的
  • 进程“一瘸一拐”并在不确定的时间后崩溃可能会造成进一步的损害,因为它将在可能损坏的程序状态下工作
  • 用户对导致崩溃的实际操作感到困惑
简言之,问题是:

如何使进程因使用TPL创建的异步
任务
而崩溃,从而使Windows错误报告能够创建有用的小型转储


提前谢谢

你可以试试这个或类似的东西:

public static Task FailFastOnException(this Task task) 
{ 
    task.ContinueWith(c => Environment.FailFast(“Task faulted”, c.Exception), 
        TaskContinuationOptions.OnlyOnFaulted | 
        TaskContinuationOptions.ExecuteSynchronously | 
        TaskContinuationOptions.DetachedFromParent); 
    return task; 
}
然后:

var t = Task.Factory.StartNew(…).FailFastOnException();
我们已经在“开火并忘记”任务中大量使用了它,如果它们由于某种原因失败,我们希望停止该过程

摘自Stephen Toub的博客:

看看(
app.config
设置):


如果未观察到与任务关联的异常, 没有等待操作,父级未连接,并且 未读取任务的System.Threading.Tasks.Task.Exception属性 例外情况被视为未被注意到

在.NET Framework 4中 默认情况下,如果具有未观察到的异常的任务是垃圾 收集后,终结器抛出异常并终止 过程过程的终止取决于 垃圾收集和终结

使开发人员更容易 要基于任务编写异步代码,.NETFramework 4.5 更改未观察到的异常的此默认行为。未被发现 异常仍然会导致引发UnobservedTaskException事件, 但默认情况下,该过程不会终止。相反,这是一个例外 在引发事件后忽略,无论事件是否 处理程序观察异常

在.NET Framework 4.5中,您可以使用 应用程序中的元素 用于启用.NET Framework 4抛出行为的配置文件 例外

您还可以在以下方式之一中指定异常行为: 以下方法:

  • 通过设置环境变量 COMPlus_ThrowUnoServedTaskException(设置 COMPlus_throwunobservedtaskeexceptions=1)

  • 通过设置注册表 中的DWORD值throwUnobservedTaskeExceptions=1 HKEY\U LOCAL\U MACHINE\SOFTWARE\Microsoft.NETFramework密钥


你能解释你为什么要这么做吗?您需要某种类型的日志记录吗?你需要内存转储吗?“为什么”可以帮助找到解决方案。是的,我需要内存转储。而来自终结器线程的内存转储是无用的。据我所知,内存转储通常是在进程(应用程序域)而不是线程上获得的。此外,这是调试应用程序的一种非常粗糙的方法。在任务中使用try…catch将在99%的情况下以易于阅读的格式为您提供有关问题的所有信息。您可以将有用的数据记录到文件或数据库中。试着看看这个实用程序:也许您可以在异常时触发它(只是一个想法)并生成转储文件。@Andrei如我所说,我不想争论如何处理异常。这个问题与此无关,因为这一争论可以持续不断,而且已经在互联网上广泛存在。但是,您可能不知道的是Windows错误报告系统,它允许供应商实际捕获报告给Microsoft的崩溃转储,以及客户从未报告的调试问题,以及调试这些问题的实际有用信息。这正是我需要知道的。谢谢我很确定
FailFast
在功能上并不等同于由于异常而导致的进程崩溃。特别是当它涉及到
最终
崩溃时的代码执行时。是的,默认行为在4.5中发生了变化,我提出这个问题时使用的是4.0。未观察到的任务异常的问题是,它发生在GC上下文中的某个未定义的时间之后。
<configuration>   
    <runtime>   
        <ThrowUnobservedTaskExceptions enabled="true"/>   
    </runtime>   
</configuration>