![](/img/trans.png)
[英]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.