今天學習線程池的時候發現,網上能搜到的都是很久以前的文檔了,大家都是照搬過去,有沒有考證都是問題。
經過測試結果已經和他們說的不一樣了,比如
<span style="white-space:pre"> </span> List<Action> actions = new List<Action>()
{
() => { Console.WriteLine("A-1"); },
() => { Console.WriteLine("A-2"); },
() => { Console.WriteLine("A-3"); },
() => { Console.WriteLine("A-4"); }
};
foreach (var action in actions)
{
ThreadPool.QueueUserWorkItem(state => action(), null);
}
輸出的結果網上流傳的是
A-4
A-4
A-4
A-4
大概就這個了
現在我用VS2012運行後的結果已經不是這樣的了,雖然順序每次都不一樣,但是4個結果都會輸出
A-2
A-3
A-1
A-4
大概這個一樣的。
同樣的代碼,出現不同的結果,應該是foreach底層代碼不同的原因,還沒有去考證。
當然,如果我們用for循環的話,結果就又不一樣了
比如寫成
for (int i = 0; i < actions.Count; i++)
{
ThreadPool.QueueUserWorkItem(state => actions[i](), null);
}
大概很多人覺得沒問題,其實會出現超出索引的錯誤,原因是開啓線程池需要時間,還沒有開啓成功的時候 for循環已經執行完了,這個時候,開啓的線程池又去調用索引i指向的函數,而for循環執行完以後,i的最後值爲4,不是3.所以超出索引。
寫成
for (int i = 0; i < actions.Count-1; i++)
{
ThreadPool.QueueUserWorkItem(state => actions[i](), null);
}
執行後的結果是
如果想要4個函數按順序執行,一種可以在主線程中等待一段時間在執行下一個,第二中可以通過ThreadPool.SetMaxThreads 和ThreadPoolMinThreads,控制線程池中線程的可執行的線程個數來實現。不知道這樣做是否合理。