C#ThreadPool.QueueUserWorkItem實例

今天學習線程池的時候發現,網上能搜到的都是很久以前的文檔了,大家都是照搬過去,有沒有考證都是問題。

經過測試結果已經和他們說的不一樣了,比如

<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,控制線程池中線程的可執行的線程個數來實現。不知道這樣做是否合理。



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