難道調用ThreadPool.QueueUserWorkItem()的時候,真是必須調用Thread.Sleep(N)嗎?
開門見山,下麵的例子中通過調用ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)的方式實現異步調用:
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: List<Action> actions = new List<Action>();
6: actions.Add(() => Console.WriteLine("A1"));
7: actions.Add(() => Console.WriteLine("A2"));
8: actions.Add(() => Console.WriteLine("A3"));
9: actions.Add(() => Console.WriteLine("A4"));
10:
11: foreach (var action in actions)
12: {
13: ThreadPool.QueueUserWorkItem(state => action(), null);
14: }
15:
16: Console.Read();
17: }
18: }
但是出現錯誤的輸出結果:
解決的方案就是在每次For循環中,調用Thread.Sleep休眠當前線程,哪怕是1ms:
1: class Program
2: {
3: static void Main(string[] args)
4: {
5: List<Action> actions = new List<Action>();
6: actions.Add(() => Console.WriteLine("A1"));
7: actions.Add(() => Console.WriteLine("A2"));
8: actions.Add(() => Console.WriteLine("A3"));
9: actions.Add(() => Console.WriteLine("A4"));
10:
11: foreach (var action in actions)
12: {
13: ThreadPool.QueueUserWorkItem(state => action(), null);
14:
15: Thread.Sleep(1);
16: }
17:
18: Console.Read();
19: }
20: }
21:
這次能夠輸出正確的結果:
我們也看到很多人確實是這麼做的。但是如果真是必須這樣的話,這樣的編程方式很難讓我接受,不知道大家有何高見。
在老趙的提示下,醒悟過來:由於被置於ThreadPool中的操作時異步的,還沒有來的執行的時候,action已經被for循環改變,永遠是同一個action對象! 嗬嗬,腦袋有時候有點轉不過彎!
所以正確的寫法是:
1: foreach (var action in actions)
2: {
3: var a = action;
4: ThreadPool.QueueUserWorkItem(state => a(), null);
5: }
作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-30 14:34:55