Task.Run和Task.Factory.StartNew之间的不同异常处理 [英] Different exception handling between Task.Run and Task.Factory.StartNew
问题描述
在使用 Task.Factory.StartNew
并尝试捕获异常
时遇到了一个问题抛出。在我的应用程序中,我有一个长期运行的任务,我希望将其封装在 Task.Factory.StartNew(..,TaskCreationOptions.LongRunning);
I encountered an issue when I was using Task.Factory.StartNew
and tried to capture an exception
that is thrown. In my application I have a long running task that I want to encapsulate in a Task.Factory.StartNew(.., TaskCreationOptions.LongRunning);
但是,当我使用 Task.Factory.StartNew
时,没有捕获到异常。但是,当我使用 Task.Run
时,它按预期工作,我认为这只是 Task.Factory.StartNew $ c的包装器$ c>(例如根据此MSDN文章)。
However, the exception isn't caught when I'm using Task.Factory.StartNew
. It is however working as I expect when I use Task.Run
, which I thought was just a wrapper on Task.Factory.StartNew
(according to for instance this MSDN article).
此处提供了一个工作示例,区别在于使用 Task.Run
时将异常写入控制台,但使用<$时则不c $ c> Factory.StartNew 。
A working example is provided here, the difference being that the exception is written to console when using Task.Run
, but not when using Factory.StartNew
.
我的问题是:
如果我有一个 LongRunning
任务,它有可能引发异常,我该如何在调用代码中处理它们?
My question would be:
if I have a LongRunning
task that has the possibility to throw exceptions, how should I handle them in the calling code?
private static void Main(string[] args)
{
Task<bool> t = RunLongTask();
t.Wait();
Console.WriteLine(t.Result);
Console.ReadKey();
}
private async static Task<bool> RunLongTask()
{
try
{
await RunTaskAsync();
}
catch (Exception e)
{
Console.WriteLine(e);
return false;
}
Console.WriteLine("success");
return true;
}
private static Task RunTaskAsync()
{
//return Task.Run(async () =>
// {
// throw new Exception("my exception");
// });
return Task.Factory.StartNew(
async () =>
{
throw new Exception("my exception");
});
}
推荐答案
您的问题是 StartNew
不能像 Task.Run
和 async
代表。 StartNew
的返回类型为 Task< Task>
(可转换为 Task
)。 外部 Task
表示方法的开始,而内部 Task
表示方法的完成(包括任何例外)。
Your problem is that StartNew
doesn't work like Task.Run
with async
delegates. The return type of StartNew
is Task<Task>
(which is convertible to Task
). The "outer" Task
represents the beginning of the method, and the "inner" Task
represents the completion of the method (including any exceptions).
要进入内部 Task
,可以使用展开
。或者,您可以使用 Task.Run
代替 StartNew
进行 async
代码。 LongRunning
只是一个优化提示,实际上是可选的。 斯蒂芬·图布(Stephen Toub)的博客很好地介绍了 StartNew
和 Run
以及为什么 Run
通常(对于)异步
代码。
To get to the inner Task
, you can use Unwrap
. Or you can just use Task.Run
instead of StartNew
for async
code. LongRunning
is just an optimization hint and is really optional. Stephen Toub has a good blog post on the difference between StartNew
and Run
and why Run
is (usually) better for async
code.
从下面的@usr注释更新: LongRunning
仅适用于 async
方法的开头(直到第一个未完成的操作是 await
ed)。因此,在这种情况下,使用 Task.Run
几乎可以肯定更好。
Update from @usr comment below: LongRunning
only applies to the beginning of the async
method (up until the first incomplete operation is await
ed). So it's almost certainly better all around to use Task.Run
in this case.
这篇关于Task.Run和Task.Factory.StartNew之间的不同异常处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!