开门见山,下面的例子中通过调用ThreadPool.QueueUserWorkItem(WaitCallback callBack, object state)的方式实现异步调用:
1: class Program
<!--CRLF-->
2: {
<!--CRLF-->
3: static void Main(string[] args)
<!--CRLF-->
4: {
<!--CRLF-->
5: List<Action> actions = new List<Action>();
<!--CRLF-->
6: actions.Add(() => Console.WriteLine("A1"));
<!--CRLF-->
7: actions.Add(() => Console.WriteLine("A2"));
<!--CRLF-->
8: actions.Add(() => Console.WriteLine("A3"));
<!--CRLF-->
9: actions.Add(() => Console.WriteLine("A4"));
<!--CRLF-->
10:
<!--CRLF-->
11: foreach (var action in actions)
<!--CRLF-->
12: {
<!--CRLF-->
13: ThreadPool.QueueUserWorkItem(state => action(), null);
<!--CRLF-->
14: }
<!--CRLF-->
15:
<!--CRLF-->
16: Console.Read();
<!--CRLF-->
17: }
<!--CRLF-->
18: }
<!--CRLF-->
但是出现错误的输出结果:
解决的方案就是在每次For循环中,调用Thread.Sleep休眠当前线程,哪怕是1ms:
1: class Program
<!--CRLF-->
2: {
<!--CRLF-->
3: static void Main(string[] args)
<!--CRLF-->
4: {
<!--CRLF-->
5: List<Action> actions = new List<Action>();
<!--CRLF-->
6: actions.Add(() => Console.WriteLine("A1"));
<!--CRLF-->
7: actions.Add(() => Console.WriteLine("A2"));
<!--CRLF-->
8: actions.Add(() => Console.WriteLine("A3"));
<!--CRLF-->
9: actions.Add(() => Console.WriteLine("A4"));
<!--CRLF-->
10:
<!--CRLF-->
11: foreach (var action in actions)
<!--CRLF-->
12: {
<!--CRLF-->
13: ThreadPool.QueueUserWorkItem(state => action(), null);
<!--CRLF-->
14:
<!--CRLF-->
15: Thread.Sleep(1);
<!--CRLF-->
16: }
<!--CRLF-->
17:
<!--CRLF-->
18: Console.Read();
<!--CRLF-->
19: }
<!--CRLF-->
20: }
<!--CRLF-->
21:
<!--CRLF-->
这次能够输出正确的结果:
我们也看到很多人确实是这么做的。但是如果真是必须这样的话,这样的编程方式很难让我接受,不知道大家有何高见。
在老赵的提示下,醒悟过来:由于被置于ThreadPool中的操作时异步的,还没有来的执行的时候,action已经被for循环改变,永远是同一个action对象! 呵呵,脑袋有时候有点转不过弯!
所以正确的写法是:
1: foreach (var action in actions)
<!--CRLF-->
2: {
<!--CRLF-->
3: var a = action;
<!--CRLF-->
4: ThreadPool.QueueUserWorkItem(state => a(), null);
<!--CRLF-->
5: }
<!--CRLF-->
分享到:
相关推荐
C#线程池 所有线程运行完毕,只是测试代码,用来弄清楚,打印信息很明确,适合初学者
c++11封装的项目中使用的线程池,lambda作为线程函数,可以使用任意形式的线程回调函数。单例模式。欢迎下载,评论
threadpool线程池学习
到我的博客去哦,有更多的源码下载的………… http://blog.csdn.net/mohongmao/
该文件采用c++11的新特性封装了linux/macos平台下的线程池。
整合前面两部分写的基于linux的线程池技术,内存池技术。能够成功测试,结果正确。代码都是基于LINUx平台的,不兼容windows,后期会更新使用c11的技术。
利用线程池来ThreadPool.QueueUserWorkItem来处理多线程问题,本人也是初学着,欢迎大家多多来探讨多线程的技术问题..
。。。
threadpool.zip
软件环境QT5,详细的实现了QT线程池,有具体调用示例,该项目博客文章,请参考:https://blog.csdn.net/qq_37529913/category_10612329.html
linux网络编程的一些技巧,包括socket,thread pool, select,epoll等
用于大型服务器地完成端口多线程池的结合IOCP+threadpool.zip
ThreadPool 线程池管理单元 带调用例子
Java版线程池ThreadPool
说明: 该采集器针对火车头采不了的特定网站定制,如需采集... 程序无须设置参数,点击“开始采集”即可,下面是本程序使用到的技术: 使用 ThreadPool.QueueUserWorkItem()多线程; 使用正则表达式匹配需采集的字符
linux下一个多线程池的实现,可以加快线程的调度,是一个学习linux线程开发的好例子
本文实例讲述了C#线程池操作方法。分享给大家供大家参考。具体如下: ... ThreadPool.QueueUserWorkItem(new WaitCallback(ShowMessage), string.Format(当前编号{0},i)); } Console.ReadLine(); }