我可以在Task.Run崩溃程序中发生异常吗?

时间:2013-04-25 10:48:39

标签: .net .net-4.5

我不是悄然吞下异常的狂热粉丝,但以下代码确实如此:

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

3 个答案:

答案 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崩溃时,调试器相当无用,看起来像这样:

enter image description here

我认为这意味着我在Task.Run这里做错了。

一个简单的解决方法是使用旧的ThreadPool.QueueUserWorkItem代替:

enter image description here

那好多了!无论如何,我真的不需要在这段代码中使用async / await;我刚刚使用Task.Run,因为输入的次数较少。

答案 2 :(得分:0)

你说你读过ThrowUnobservedTaskExceptions;您是否真的尝试在配置中将ThrowUnobservedTaskExceptions设置为true来运行您的程序?

.NET 4中的默认行为是,未观察到的Task异常会影响整个过程。

.NET 4.5中的默认行为是,未观察到的Task例外不会关闭进程。由于您在.NET 4.5上运行,因此将ThrowUnobservedTaskExceptions设置为true应该完全符合您的要求。