我在使用 Task.Factory.StartNew
并 try catch 抛出的 exception
时遇到问题。在我的应用程序中,我有一个长时间运行的任务,我想将其封装在 Task.Factory.StartNew(.., TaskCreationOptions.LongRunning);
但是,当我使用 Task.Factory.StartNew
时,异常没有被捕获。然而,当我使用 Task.Run
时,它的工作方式与我预期的一样,我认为它只是 Task.Factory.StartNew
的包装器(根据例如 this MSDN article ) .
此处提供了一个工作示例,不同之处在于使用 Task.Run
时将异常写入控制台,但使用 Factory.StartNew
时则不会。
我的问题是:
如果我有一个可能抛出异常的 LongRunning
任务,我应该如何在调用代码中处理它们?
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
表示方法的完成(包括任何异常)。
进入内部Task
, 你可以使用 Unwrap
.或者你可以只使用 Task.Run
而不是 StartNew
对于 async
代码。 LongRunning
只是一个优化提示,实际上是可选的。 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
编辑)。所以使用 Task.Run
几乎肯定更好在这种情况下。
关于c# - Task.Run 和 Task.Factory.StartNew 之间不同的异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14729736/