我不是悄然吞下异常的狂热粉丝,但以下代码确实如此:
Task.Run(() =>
{
var obj = DoSomethingCpuIntensive(); // returns null, due to a bug
obj.DoMoreStuff();
Console.WriteLine("after"); // never get here; program continues running
});
我已经阅读了ThrowUnobservedTaskExceptions配置值,但这没有用,因为我从来没有对返回的Task
做任何事情(编辑:实际上它确实有帮助,但只在发布版本中)。
有没有办法让未处理的异常导致程序崩溃?我是否以某种我不应该使用的方式使用Task.Run
?
答案 0 :(得分:2)
我强烈建议您使用Task.Run
而不是ThreadPool.QueueUserWorkItem
。
首先,退后一步。 DoSomethingCpuIntensive
的目的是什么?如果您正在计算某个值,我建议您将其返回,因此您有一个Task<T>
而不是Task
。例如,(假设DoMoreStuff
不是CPU密集型的):
async Task DoWorkAsync()
{
var obj = await Task.Run(() => DoSomethingCpuIntensive());
obj.DoMoreStuff();
}
我想要了解的想法是,即使“结果”只是“成功”或“例外”,您的代码应该关心后台操作的结果。你的代码更干净。否则,您将拥有一个半独立系统,您只能通过检测应用程序状态的变化来响应。更麻烦。
那就是说,如果你真的想要拥有半独立系统并且你希望它在你的进程失败时崩溃,那么ThrowUnobservedTaskExceptions
就是你想要的。我不确定你为什么觉得它没用。
答案 1 :(得分:1)
看来像这样使用Task.Run
确实是一个错误。我想我应该await
它,否则上面会发生愚蠢的事情。
当它与await
崩溃时,调试器相当无用,看起来像这样:
我认为这意味着我在Task.Run
这里做错了。
一个简单的解决方法是使用旧的ThreadPool.QueueUserWorkItem
代替:
那好多了!无论如何,我真的不需要在这段代码中使用async / await;我刚刚使用Task.Run
,因为输入的次数较少。
答案 2 :(得分:0)
你说你读过ThrowUnobservedTaskExceptions
;您是否真的尝试在配置中将ThrowUnobservedTaskExceptions
设置为true
来运行您的程序?
.NET 4中的默认行为是,未观察到的Task
异常会影响整个过程。
.NET 4.5中的默认行为是,未观察到的Task
例外不会关闭进程。由于您在.NET 4.5上运行,因此将ThrowUnobservedTaskExceptions
设置为true
应该完全符合您的要求。