簡體   English   中英

如何等待異步任務

[英]How to wait on Async tasks

static void Main(string[] args)
{
    Action myAction = async () =>
    {
        await Task.Delay(5);
        Console.WriteLine(Interlocked.Add(ref ExecutionCounter, 1));                
    };

    var actions = new[] { myAction, myAction, myAction };

    Task.WaitAll(actions.Select(a => Execute(a)).ToArray());  //This blocks, right?

    Console.WriteLine("Done waiting on tasks.");
    Console.ReadLine();
}

static int ExecutionCounter = 0;

private static Task Execute(Action a)
{
    return Task.Factory.StartNew(async () =>
    {
        await Task.Delay(5);
        a();
    });
}

這看起來很簡單,但是自然地,輸出總是看起來像這樣(數字的順序當然會改變):

等待任務完成。

2

1個

3

我在這里想念什么? 為什么Task.WaitAll不會像我期望的Task.WaitAll阻塞?

因此,這里有幾個單獨的錯誤。

首先,對於Execute ,您將StartNewasync lambda一起使用。 由於StartNew沒有像Task.Run這樣的Task<Task>返回過載, Task.Run您有一個返回Task的方法,該方法指示異步操作何時完成啟動 ,而不是異步操作何時完成,這意味着Execute返回的Task將立即完成,而不是在Delay完成或您調用的操作完成之后。 此外,運行異步方法時根本沒有理由完全使用StartNewRun ,您可以正常執行它們並await它們,而無需將它們推送到線程池線程中。

接下來, Execute接受一個Action ,這意味着它是一個同步方法,不計算任何值。 您提供的是一個異步方法,但是由於委托沒有返回Task ,因此Execute無法await它。 如果希望Execute處理異步方法,則需要接受返回Task的委托。

因此,鑒於所有Execute應該看起來像這樣。

private static async Task Execute(Func<Task> action)
{
    await Task.Delay(TimeSpan.FromMilliseconds(5));
    await action();
}

接下來進入Main方法。 如前所述,當您嘗試提供async方法時, Execute接受Action 這意味着在運行操作時,代碼將在您的操作完成之前繼續執行。 您需要將其調整為使用Task返回方法。

所有一切后,你的代碼仍然有它的競爭條件,在概念層面,這將阻止你獲得理論上的結果以正確的順序。 您正在並行執行3個不同的操作,因此,它們可以按任何順序完成。 在原子地遞增計數器的同時,有可能一個線程輸出一個計數器,然后運行另一個線程,遞增計數器,打印其值,然后讓另一個線程再次運行並打印出該值,這可能是因為您所擁有的,即使修復了上述所有錯誤之后也是如此。 為了確保按順序打印值,您需要確保增量和控制台寫入是原子執行的

現在,您可以像這樣寫出Main方法:

int ExecutionCounter = 0;
object key = new object();
Func<Task> myAction = async () =>
{
    await Task.Delay(TimeSpan.FromMilliseconds(5));
    lock (key)
    {
        Console.WriteLine(++ExecutionCounter);
    }
};

var actions = new[] { myAction, myAction, myAction };

Task.WaitAll(actions.Select(a => Execute(a)).ToArray());  //This blocks, right?

是的,正如您的評論所提到的,調用WaitAll將阻止,而不是異步。

暫無
暫無

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

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