如何在 loop 中使用 await 做到並行執行 ?

諮詢區

  • Satish

我建了一個 Console 程序想用異步的方式處理集合,我做了兩個版本。

  1. 使用 parallel 方式遍歷集合。

  2. 使用 async,await 遍歷集合。

測試下來,我發現 async/await 的執行方式是同步的,這就很尷尬了,我如何用 async/await 實現  parallel 的方式呢?這是我寫的測試代碼:


class Program
{
    static void Main(string[] args)
    {
        var worker = new Worker();
        worker.ParallelInit();
        var t = worker.Init();
        t.Wait();
        Console.ReadKey();
    }
}

public class Worker
{
    public async Task<boolInit()
    {
        var series = Enumerable.Range(15).ToList();
        foreach (var i in series)
        {
            Console.WriteLine("Starting Process {0}", i);
            var result = await DoWorkAsync(i);
            if (result)
            {
                Console.WriteLine("Ending Process {0}", i);
            }
        }

        return true;
    }

    public async Task<boolDoWorkAsync(int i)
    {
        Console.WriteLine("working..{0}", i);
        await Task.Delay(1000);
        return true;
    }

    public bool ParallelInit()
    {
        var series = Enumerable.Range(15).ToList();
        Parallel.ForEach(series, i =>
        {
            Console.WriteLine("Starting Process {0}", i);
            DoWorkAsync(i);
            Console.WriteLine("Ending Process {0}", i);
        });
        return true;
    }
}

回答區

  • Tim S.

你使用 await 的姿勢無形中就告訴 C# 你每loop一次都要await一下,這種方式肯定就串行了,你可以將需要並行迭代的 item 封裝到 Task.WhenAll 中,然後用 await 一次等待就可以了,參考如下代碼:


public async Task<boolInit()
{
    var series = Enumerable.Range(15).ToList();
    var tasks = new List<Task<Tuple<intbool>>>();
    foreach (var i in series)
    {
        Console.WriteLine("Starting Process {0}", i);
        tasks.Add(DoWorkAsync(i));
    }
    foreach (var task in await Task.WhenAll(tasks))
    {
        if (task.Item2)
        {
            Console.WriteLine("Ending Process {0}", task.Item1);
        }
    }
    return true;
}

public async Task<Tuple<intbool>> DoWorkAsync(int i)
{
    Console.WriteLine("working..{0}", i);
    await Task.Delay(1000);
    return Tuple.Create(i, true);
}

點評區

相信這幾年大家做的新項目都是滿屏的 await,async 了吧,異步的優點還是大大提高了驅動設備的利用率,不然也不會有各種導致堆碎片化的 Overlapped 🤣,異步也是一種串行,學會怎麼在異步串行中組合並行的方式,對開發來說很有用,學習了。


本文分享自微信公衆號 - 一線碼農聊技術(dotnetfly)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閱讀的你也加入,一起分享。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章