[英]Fire and forget, using `Task.Run` or just calling an async method without `await`
[英]fire and forget an async Task method sometimes not invoke
我有一个异步方法:
public async Task DoSomethingAsync(){
...
await ...
await ...
....
return await SaveAsync();
}
在大多数时候,我通过以下方式调用此方法:
await DoSomethingAsync()
此调用按预期工作。 但在某个地方,我需要将此方法称为火,并忘记:
public void OtherMethod()
{
...
DoSomethingAsync(); //fire and forget here
}
在这种情况下,有时Task DoSomethingAsync()
运行并完成,但有时任务永远不会被调用(或者在DoSomethingAsync()
调用一些await
但永远不会完成最后一次await SaveAsync();
)。
我正在尝试通过以下代码确保以火灾和忘记方式调用任务:
public void OtherMethod()
{
...
Task.Factory.StartNew(() =>
{
await DoSomethingAsync();
}); //fire and forget again here
}
但是,这不符合预期。 所以我的问题是:
如何在没有await
情况下调用DoSomethingAsync()
将始终运行并完成? (我不关心AppDomain重启/崩溃的情况)
如果我删除所有async/await
内码DoSomethingAsync()
和REPLACE await
通过.ContinueWith()
然后调用Task DoSomethingAsync()
没有async
在方法声明)将被调用,并确保完成(忽略大小写的AppDomain重新启动/崩溃),如果是的话,从通话中退出多长时间(我不认为如果在10分钟后调用任务我会很高兴)?
您可能在DoSomethingAsync
某处遇到异常,由于您忽略了该任务,因此无法观察到该异常。 这正是您要求的行为,因为您告诉代码“忘记”任务。
要观察异常,你不能“忘记”任务:
public Task OtherMethodAsync()
{
...
return DoSomethingAsync();
}
在某些时候, await
(或Wait
)返回的任务。 这就是你知道任务将运行和完成的方式。
等待应该工作正常,所以这里可能还有其他东西正在等待你的一个或多个方法。 有几种可能性:
如果您可以使用VS调试器附加并观察发生的情况,请尝试暂停并查看Parallel Stacks视图。 这应该有助于缩小考虑的可能性。
正如斯蒂芬指出的那样,当你称之为“即发即忘”时,也可能发生异常。 如果您还没有,请确保处理TaskScheduler.UnobservedTaskException以记录此类事件。 请注意,这是从终结器调用的,因此调用它的时间是不确定的。 这可能会使调试变得棘手,因为事件可能要比导致异常的实际事件晚得多。 因此,我建议遵循Stephen的建议并将任务保存到等待或稍后等待其他地方。
ASP.NET通常不允许在请求中启动fire-and-forget(async void)操作。 有关此行为的进一步说明以及一些可能的解决方法,请参阅https://stackoverflow.com/a/22484832/59641 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.