簡體   English   中英

為什么使用Parallel.ForEach時主線程被阻塞

[英]why the primary thread is blocked when using Parallel.ForEach

下面是我的代碼:

class Program
{
    static void Main(string[] args)
    {
        Test();
    }

    static void Test()
    {
        string[] strList = { "first", "second", "third" };
        Parallel.ForEach(strList, currStr =>
        {
            Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is handling {currStr}");
            if (Thread.CurrentThread.ManagedThreadId != 1)  //if not primary thread, sleep for 5 secs
            {
                Thread.Sleep(5000);
            }
        });
        Console.WriteLine($"Here is thread {Thread.CurrentThread.ManagedThreadId}");
        ...
        doMoreWork();
        ...
    }
}

因此Parallel.ForEach從ThreadPool以及現有的主線程中獲取兩個線程。 輸出為:

線程1首先處理

線程3處理第二

線程4正在處理第三項

5秒后:

這是線程1

顯然,線程1(主線程)被阻塞。 但是,為什么主線程被阻塞了? 我可以有點主線程被阻塞以等待其他線程完成其工作的想法。 但這不是很低效,因為主線程被阻塞了,所以直到所有其他線程都完成后,它才能繼續執行doMoreWork()

還有其他可能如何工作? 並行for循環的目的是通過並行執行部分計算來加快計算速度。 該程序無法繼續執行,直到循環的所有部分都已完成(並且可以計算出最終的計算結果)。 目的不是在啟動線程繼續前進的過程中交出異步執行的工作。 您為該工作使用了錯誤的工具。 您應該查看Task對象。

它不是低效的,它只是您編碼的方式。 雖然並行線程執行很有用,但順序執行也很有用。 Parallel.Foreach的主要目的是通過在多個線程之間划分枚舉來迭代枚舉。 例如,讓Foreach循環通過將操作應用於枚舉中的每個項目來計算一個值。 然后,您要在對doMoreWork的調用中使用此單個值。 如果並行執行Foreach循環和doMoreWork,則必須引入某種等待形式,以確保在調用doMoreWork之前完成foreach。

您可能需要看一下Task Class文檔和示例。 如果您確實希望同時在單獨的線程中運行Parallel.Foreach和doMoreWork,則可以使用Task.Run啟動一個函數(或lambda),然后獨立等待它們完成。

我將注意到並行執行不能保證效率或速度。 有許多因素需要考慮,例如阿姆達爾定律 ,鎖定內存以確保一致性的效果,系統總資源等。這是一個非常大的話題。

暫無
暫無

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

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