[英]Is it safe not to wait for all tasks
假設我有以下操作方法:
[HttpPost]
public async Task<IActionResult> PostCall()
{
var tasks = new List<Task<bool>>();
for (int i = 0; i < 10; i++)
tasks.Add(Manager.SomeMethodAsync(i));
// Is this line necessary to ensure that all tasks will finish successfully?
Task.WaitAll(tasks.ToArray());
if (tasks.Exists(x => x.Result))
return new ObjectResult("At least one task returned true");
else
return new ObjectResult("No tasks returned true");
}
Task.WaitAll(tasks.ToArray())
必須確保所有任務都能成功完成? Exists
無法訪問其Result
的任務是否會成功完成后台執行? 或者有些任務(沒有等待)會被刪除,因為它們不會附加到請求中嗎? 有沒有更好的實施我錯過了?
是的,除非等待它們(等待等待的東西),否則不保證任務完成
在您的情況下,您應該進行的主要更改是創建Task.WaitAll
await Task.WhenAll(tasks);
所以它實際上是異步的。 如果你只是想等待一個任務返回,使用WhenAny
代替。
在您提供的實現下, Task.WaitAll
調用阻止調用線程,直到所有任務都完成。 它只會進入下一行,並在發生這種情況后執行Exists
檢查。 如果刪除Task.WaitAll
,則Exists
檢查將導致調用線程按順序阻塞每個任務; 即它首先阻止tasks[0]
; 如果返回false,則會阻塞tasks[1]
,然后阻塞tasks[2]
,依此類推。 這是不可取的,因為如果任務完成無序,它不允許您的方法提前完成。
如果您只需要等到任何一個任務首先返回true,那么您可以使用Task.WhenAny
。 這將使任何任務完成后您的異步方法恢復。 然后,您可以檢查它是否評估為true並立即返回成功; 否則,您將繼續重復剩余任務集的過程,直到沒有剩余任務為止。
如果您的代碼作為應用程序(WPF,WinForms,Console)運行,那么剩余的任務將繼續在線程池上運行直到完成,除非應用程序關閉。 線程池線程是后台線程,因此如果所有前台線程都已終止(例如因為所有窗口都已關閉),它們將不會使進程保持活動狀態。
由於您運行的是Web應用程序,因此您可能會在任務完成之前回收應用程序池。 未完成的任務是即發即棄的,因此運行時未被跟蹤。 為了防止這種情況發生,您可以通過HostingEnvironment.QueueBackgroundWorkItem
方法在運行時注冊它們,如注釋中所示。
[HttpPost]
public async Task<IActionResult> PostCall()
{
var tasks = Enumerable
.Range(0, 10)
.Select(Manager.SomeMethodAsync)
.ToList();
foreach (var task in tasks)
HostingEnvironment.QueueBackgroundWorkItem(_ => task);
while (tasks.Any())
{
var readyTask = await Task.WhenAny(tasks);
tasks.Remove(readyTask);
if (await readyTask)
return new ObjectResult("At least one task returned true");
}
return new ObjectResult("No tasks returned true");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.