C#多线程之三:解决多线程编程中大并发数等待唤醒的问题
2014-10-20 10:39
453 查看
在移动交通流调查项目的一个算法分析程序中,碰到一个业务问题:用户采集上传的基站定位数据需要进行分析预处理,方案是先按预定格式解析文件并从中提取出成百上千个基站定位数据记录,并合并相同的基站点,根据获取到的基站位置信息作为参数,去请求google 基站定位 api,从而得到对应的基站定位经纬度等信息,接下来再加上华工的算法分析。
在执行华工算法分析逻辑之前,调用谷歌api这一步必需全部完成;网络请求是个耗时的过程,故对每一个请求开启单独的线程(同时请求可能数百个,这里通过Semaphore信号量来控制每次发出请求的最大数,该部分的讨论不再本话题之类)。
问题出来了,那么如何知道所有的网络请求全部完成了,可以进行下一步算法分析呢?答案是利用前面讲的ManualResetEvent来处理;于是有下面的写法
?
?
运行好像没有问题,程序按原定计划执行;但是当线程数大于64个之后抛出异常
WaitHandles must be less than or equal to 64
原来WaitHandle.WaitAll(listEvent.ToArray()); 这里listEvent线程数不能超过64个
以前解决方法:
下面是吴建飞以前的方案:既然WaitHandle.WaitAll方法只能唤醒64个ManualResetEvent对象,那么就采用
?
采用这种复杂集合;集合的每个元素也是一个集合(内部每个集合包含最大64个ManualResetEvent对象);和上面一样 把每个线程相关的ManualResetEvent对象添加到该集合;
//主线程等待网络请求全部完成
?
该方案运用起来比较复杂,而且会导致创建大量的ManualResetEvent对象;
现在的设计目标是这种对文件的分析是多任务同时进行的,也就是说会产生的ManualResetEvent对象List<List<ManualResetEvent>>.Size() * 任务数(N个文件上传)
改进的解决方法:
原理:封装一个ManualResetEvent对象,一个计数器current,提供SetOne和WaitAll方法;
主线程调用WaitAll方法使ManualResetEvent对象等待唤醒信号;
各个子线程调用setOne方法 ,setOne每执行一次current减1,直到current等于0时表示所有子线程执行完毕 ,调用ManualResetEvent的set方法,这时主线程可以执行WaitAll之后的步骤。
目标:减少ManualResetEvent对象的大量产生和使用的简单性。
在这里我写了个封装类:
?
注释写的很清楚了:本质就是只通过1个ManualResetEvent 对象就可以实现同步N(N可以大于64)个线程
下面是测试用例:
?
输出:
… 省略 ...
从结果上看线程执行的完成的时间顺序是不固定的;并且只有在所有100个网络请求任务完成后,才显示可以继续下面的分析。
与上面的方案是一样的效果,但是本方案使用非常简单,出错的概念小,免去了创建大量 ManualResetEvent 对象的烦恼
该解决方案可以适用与.net framework 2.0 以上的运行时。
tips:在.net framework 4.0 中有一个CountdownEvent对象可以实现类似的功能;
不过目前公司大多数项目运行时还是基于.net framework 2.0 和 3.5
微软企业开发技术 | 移动开发(Google Android、Windows Mobile)技术| 嵌入式系统设计与开发 | JAVA开发
其他版本
.NET Framework 4.5
此主题尚未评级-
评价此主题
System.Threading.CountdownEvent是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定。
CountdownEvent专门用于以下情况:您必须使用
ManualResetEvent 或ManualResetEventSlim,并且必须在用信号通知事件之前手动递减一个变量。例如,在分叉/联接方案中,您可以只创建一个信号计数为
5 的 CountdownEvent,然后在线程池上启动五个工作项,并且让每个工作项在完成时调用Signal。每次调用
Signal 时,信号计数都会递减 1。在主线程上,对
Wait 的调用将会阻塞,直至信号计数为零。
======================================
/article/6204691.html
http://technet.microsoft.com/zh-CN/library/dd997365(v=vs.100)
在移动交通流调查项目的一个算法分析程序中,碰到一个业务问题:用户采集上传的基站定位数据需要进行分析预处理,方案是先按预定格式解析文件并从中提取出成百上千个基站定位数据记录,并合并相同的基站点,根据获取到的基站位置信息作为参数,去请求google 基站定位 api,从而得到对应的基站定位经纬度等信息,接下来再加上华工的算法分析。
在执行华工算法分析逻辑之前,调用谷歌api这一步必需全部完成;网络请求是个耗时的过程,故对每一个请求开启单独的线程(同时请求可能数百个,这里通过Semaphore信号量来控制每次发出请求的最大数,该部分的讨论不再本话题之类)。
问题出来了,那么如何知道所有的网络请求全部完成了,可以进行下一步算法分析呢?答案是利用前面讲的ManualResetEvent来处理;于是有下面的写法
?
WaitHandles must be less than or equal to 64
原来WaitHandle.WaitAll(listEvent.ToArray()); 这里listEvent线程数不能超过64个
以前解决方法:
下面是吴建飞以前的方案:既然WaitHandle.WaitAll方法只能唤醒64个ManualResetEvent对象,那么就采用
?
//主线程等待网络请求全部完成
?
现在的设计目标是这种对文件的分析是多任务同时进行的,也就是说会产生的ManualResetEvent对象List<List<ManualResetEvent>>.Size() * 任务数(N个文件上传)
改进的解决方法:
原理:封装一个ManualResetEvent对象,一个计数器current,提供SetOne和WaitAll方法;
主线程调用WaitAll方法使ManualResetEvent对象等待唤醒信号;
各个子线程调用setOne方法 ,setOne每执行一次current减1,直到current等于0时表示所有子线程执行完毕 ,调用ManualResetEvent的set方法,这时主线程可以执行WaitAll之后的步骤。
目标:减少ManualResetEvent对象的大量产生和使用的简单性。
在这里我写了个封装类:
?
下面是测试用例:
?
… 省略 ...
从结果上看线程执行的完成的时间顺序是不固定的;并且只有在所有100个网络请求任务完成后,才显示可以继续下面的分析。
与上面的方案是一样的效果,但是本方案使用非常简单,出错的概念小,免去了创建大量 ManualResetEvent 对象的烦恼
该解决方案可以适用与.net framework 2.0 以上的运行时。
tips:在.net framework 4.0 中有一个CountdownEvent对象可以实现类似的功能;
不过目前公司大多数项目运行时还是基于.net framework 2.0 和 3.5
微软企业开发技术 | 移动开发(Google Android、Windows Mobile)技术| 嵌入式系统设计与开发 | JAVA开发
CountdownEvent
.NET Framework 4其他版本
.NET Framework 4.5
此主题尚未评级-
评价此主题
System.Threading.CountdownEvent是一个同步基元,它在收到一定次数的信号之后,将会解除对其等待线程的锁定。
CountdownEvent专门用于以下情况:您必须使用
ManualResetEvent 或ManualResetEventSlim,并且必须在用信号通知事件之前手动递减一个变量。例如,在分叉/联接方案中,您可以只创建一个信号计数为
5 的 CountdownEvent,然后在线程池上启动五个工作项,并且让每个工作项在完成时调用Signal。每次调用
Signal 时,信号计数都会递减 1。在主线程上,对
Wait 的调用将会阻塞,直至信号计数为零。
======================================
/article/6204691.html
http://technet.microsoft.com/zh-CN/library/dd997365(v=vs.100)
相关文章推荐
- C#多线程之三:解决多线程编程中大并发数等待唤醒的问题
- 解决多线程编程中大并发数等待唤醒的问题
- C#多线程之解决多线程编程中大并发数等待唤醒的问题
- C#多线程之三:解决多线程编程中大并发数等待唤醒的问题
- java多线程的等待唤醒机制及如何解决同步过程中的安全问题
- Java基础 多线程 解决安全问题 等待唤醒机制 Lock Condition interrupt join setPriority yield
- 网络编程三---多线程/进程解决并发问题
- 使用ThreadLocal解决多线程的并发问题
- 并发编程:c++11 多线程中随机数重复问题
- 什么情景下应该考虑 多线程 编程来解决问题
- Java--servlet + ThreadLocal解决多线程并发问题及实例
- java多线程-线程间通信-示例代码-解决安全问题-等待唤醒机制wait()notify()notifyAll()
- 并发危险:解决多线程代码中的 11 个常见的问题
- C++ 多线程编程解决CPU占用率高问题
- 并发危险:解决多线程代码中的11个常见问题
- 采用多线程方式,解决由于查询等待造成winfrom假死问题
- Java中ThreadLocal类(解决多线程程序中并发问题的一种新思路,主要为参数的拷贝问题)
- 应用多线程:解决等待超时问题
- 【转】并发危险:解决多线程代码中的 11 个常见的问题
- php中,高并发状态下文件的读写 (解决多线程同时读写一个文件的问题)