![](/img/trans.png)
[英]How to unblock “primary” thread for UI in winforms (using 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.