如何在 Task 引发异常而不等待终结器的情况下使应用程序崩溃
本文关键字:情况下 崩溃 应用程序 等待 Task 异常 | 更新日期: 2023-09-27 18:36:47
我们在.Net 4(没有可用的异步等待)应用程序中使用任务,有时它们用于启动"即发即弃"操作,如下所示:
private void Test()
{
Task task = Task.Factory.StartNew(() =>
{
throw new ApplicationException("Test");
});
}
我们希望此异常在不等待任务的情况下使应用程序崩溃(否则将其放在任务中是没有意义的,至少在我们的场景中是这样),并且无需等待终结器,因为我们希望在发生意外错误时关闭应用程序以避免状态损坏(我们正在保存异常发生时存在的状态)。
我的猜测是,我们应该以某种方式使用延续任务,但这会将延续代码放在另一个不会使应用程序崩溃的任务中,所以我在这里被阻止了。
任何帮助将不胜感激
编辑:如果切换到线程池,结果是预期的。以下代码使应用程序崩溃:
ThreadPool.QueueUserWorkItem((c) =>
{
throw new ApplicationException("Test");
});
我终于找到了如何做到这一点,即使它有点复杂:
namespace ThreadExceptions
{
using System;
using System.Threading;
using System.Threading.Tasks;
public static class TaskExtensions
{
public static Task ObserveExceptions(this Task task)
{
return task.ContinueWith((t) =>
{
ThreadPool.QueueUserWorkItem((w) =>
{
if (t.Exception != null)
{
foreach (Exception ex in t.Exception.InnerExceptions)
{
throw new TaskException(ex);
}
}
});
}, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.PreferFairness);
}
}
}
这将使应用程序崩溃而无需等待任务。这就是我一直在寻找的。
使用 FailFast 尝试此解决方案
此方法在不运行任何活动的情况下终止进程 尝试/最终块或终结器。
private void Test()
{
Task task = Task.Factory.StartNew(() =>
{
Environment.FailFast("Test", new ApplicationException("Test"));
});
}
您可以编写自己的Task
类来包装要使用的各种Task
方法,并向其添加异常处理。
例如:
public static class TaskWithExceptionHandling
{
public static Task StartNew(Action action)
{
var task = Task.Factory.StartNew(action);
task.ContinueWith(exceptionHandler, TaskContinuationOptions.OnlyOnFaulted);
return task;
}
private static void exceptionHandler(Task task)
{
// Handle unhandled aggregate task exception from 'task.Exception' here.
Console.WriteLine("Exception: " + task.Exception.GetBaseException().Message);
}
}
您将像这样替换Task
类:
Task task = TaskWithExceptionHandling.StartNew(() =>
{
throw new InvalidOperationException("Test exception");
});
Console.ReadLine();