簡體   English   中英

完成多個任務后如何調用一個任務

[英]How to call one task after completion of multiple tasks

我有List任務,這些任務做了一些無關的工作。 我需要的是顯示消息框,以防所有任務正確完成其工作。 我嘗試了幾種方法,但是沒有任何一種方法可以正常工作。 最簡單的方法可以使用

Task continuation = Tasks.WhenAll(tasks);
continuation.ContinueWith(obj => {
    show messagebox
});

但是ContinueWith仍然對所有任務運行,而不僅僅是繼續任務。 我試圖設置取消令牌或使用符號,但是任務同時運行,因此無法正常工作。

我將不勝感激。

ContinueWith仍然針對所有任務運行,而不僅僅是繼續任務。

不對 當所有任務完成執行時, ContinueWith將運行一次。 您可以很容易地模擬它:

var tasks = new[] { Task.Delay(1000), Task.Delay(2000), Task.Delay(500) };
Task.WhenAll(tasks).ContinueWith(x => Console.WriteLine("Finished"));
Console.Read();

您只會看到“完成”打印一次。

如果可以的話,我當然更願意使用await而不是附加延續:

public async Task FooAsync()
{
    var tasks = new[] { Task.Delay(1000), Task.Delay(2000), Task.Delay(500) };
    await Task.WhenAll(tasks);
    Console.WriteLine("Done").
}

在非異步功能中使用任務與在異步功能中使用任務之間是有區別的。

對您的問題的簡短回答不是使用Task.WhenAll,而是使用Task.WaitAll。 所有任務完成后,此函數將返回。 之后,您可以繼續下一條語句,顯示消息框

private void OnButton1_clicked(object sender, ...)
{
    Task task1 = StartTask1(...);
    Task task2 = StartTask2(...);
    // do other things, after a while wait until all tasks are finished
    Task.WaitAll(new Task[] {task1, task2};
    MessageBox.Show(...)
 }

問題:等待任務完成時,您的用戶界面無響應

使UI保持響應的一種簡單方法是使用異步-等待。 異步等待使您的程序保持響應,因為只要該過程必須等待冗長的時間才能完成,控制權就會交還給您的主程序,該程序有時間做其他事情。

關於async-await的好處是代碼仍然看起來是順序的。 您不必按“完成此任務后再執行其他任務”的意思使用ContinueWith。

要使用async-await,您要做的就是聲明事件處理程序為async。 在事件處理程序中,您可以調用任何其他異步函數。 每當需要調用函數的結果時,就等待任務。

您的代碼如下所示:

private async void OnButton1_clicked(object sender, ...)
{
    Task task1 = StartTask1(...);
    Task task2 = StartTask2(...);
    // while the tasks are being performed do other things,
    // after a while wait until all tasks are finished
    await Task.WhenAll(new Task[] {task1, task2};
    MessageBox.Show(...)
 }

此代碼確保在等待UI時可以響應。 我要做的唯一的事情是:

  1. 聲明事件處理程序異步
  2. 使用WhenAll而不是WaitAll。 WhenAll返回一個(等待的)任務
  3. 等待WhenAll完成。

為了能夠使用async-await,請牢記以下幾點:

  • 如果您的函數必須等待較長的時間,請以異步函數的形式啟動冗長的函數並等待它
  • 為了能夠使用await,必須將您的函數聲明為異步
  • 每個異步函數都返回Task而不是void和Task <Tresult >而不是TResult
  • 有一個例外:異步事件處理程序返回void
  • 等待任務的返回為空,等待任務<TResult >的返回為Tresult

Eric Lippert(感謝Eric!)在Stackoverflow中對async-await進行了如下解釋-async / await-這種理解正確嗎?

假設早餐,你必須烤面包和煮雞蛋。 有幾種方案:

  1. 開始敬酒面包。 等待直到完成。 開始煮雞蛋,直到煮完為止。 同步處理。 在等待面包烤面包時,您無能為力。
  2. 開始烘烤面包,而烘烤面包時,則開始煮雞蛋。 雞蛋煮熟后,待面包烘烤完畢。 這稱為異步,但不是並發的。 它是由主線程完成的,只要該線程執行某項操作,主線程就無法執行其他任何操作。 但是在等待時,它有時間做其他事情(例如泡茶)
  3. 雇用廚師烤面包和煮雞蛋。 等到兩者都完成。 異步和並發:工作由不同的線程完成。 這是最昂貴的,因為您必須啟動新線程。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM