我遇到一个问题,当我使用Task.Factory.StartNew
,并试图捕捉到一个exception
时引发。 在我的应用我有,我想在一个封装一个长期运行的任务Task.Factory.StartNew(.., TaskCreationOptions.LongRunning);
然而,当我使用的异常没有被捕获Task.Factory.StartNew
。 然而工作,我希望当我使用Task.Run
,我认为是只是一个包装Task.Factory.StartNew
(按照例如这个MSDN文章 )。
工作示例这里提供,不同之处在于例外写入使用时安慰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");
});
}
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).
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.
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.
我拉我的一些评论到答案,因为他们原来是有帮助的:
LongRunning
等同于强制在实践中创造了一个新的线程。 而你的异步方法可能不是上线很长时间(它是采取关闭在第一的await点)。 你不想LongRunning在这种情况下。
不要紧多久异步方法运行。 线程是在第一个的await破坏(即在未完成任务的工作)。
编译器可以使用此提示以任何方式? 编译器一般不能分析任何主要方式你的代码。 另外,编译器不知道的东西TPL。 第三方物流是一个图书馆。 而这个图书馆将永远只是推出一个新的线程。 指定LongRunning
当且仅当你的任务几乎总是燃烧100%的CPU多秒,或将多个秒封锁概率非常高。
我的猜测是你不想LongRunning
因为如果你封锁,你为什么要摆在首位使用异步这里? 异步大约是不会阻止,但下车的线程。
它应该是可能的,当你第一次解开任务:
await RunTaskAsync().Unwrap();
或者:
await await RunTaskAsync();