C#多线程实现方法——线程池(Thread Pool)
2012-12-26 23:36
477 查看
ThreadPool使用
需要定义waitcallback委托形式如public delegate void WaitCallback(object state);例如如下例子:
static private void ThreadWorker(object state) { int num = (int)state; if (num > 0) { for (int i = 0; i < 3; i++) { Thread.Sleep(1000);// sleep for one second num++; Console.WriteLine(string.Format("Current thread {0} deal with {1}.", Thread.CurrentThread.ManagedThreadId, num)); } } return; }就是一个简单的隔一秒增加一的自增器。
调用ThreadPool的方法很简单,需要引用System.Threading。接着使用QueueUserWorkItem或者UnsafeQueueUserWorkerItem。
public static class Th read Pool { } public static bool QueueUserWorkltem (WaitCa llback ca llBack) ; public stat ic bool QueueUserWork ltem ( WaitCallback callBack, object state ) ; [Secu rityPermi ssion (Secu rityAction .Lin kDemand, Flags= Secu rityPermi ssionFlag . ControlPol icy l Secu rityPermi ssionF lag . Cont rolEvidence )] public stat ic bool UnsafeQueueUserWorkltem ( WaitCallback callBac k, obj ect state ) ;可以接受一个参数传递给异步线程。
结合前面的自增器,下面例子是申请5个异步线程来运行上述的自增器,传递的值是10,20,30,40,50。接着等待足够长的时间来等待所有线程池里的工作完成。
for (int i = 1; i <= 5; i++) ThreadPool.QueueUserWorkItem(ThreadWorker, i * 10); for (int i = 0; i < 5; i++) Thread.Sleep(1000);// wait for all threads finish从上面可以看到线程池的使用非常的简单,只需要提供符合waitcallback的委托的工作函数,接着调用QueueUserWorkItem或者UnsafeQueueUserWorkItem添加到线程池里就ok了。但是线程池的缺点也是有的,首先,没有简单的方法来知道工作线程已经完成了,不想asynchronous中提供那么多种等待异步结束的方法,更谈不上能够添加回调函数,也不想thread那样可以使用join函数来等待线程或者使用abort函数中断正在运行的工作项。同时由于它是后台线程,也就是意味如果没有前台线程,程序就关闭,所有正在运行的或者还留在线程池里的工作项就给强制中断。所以不能将一些类似保存退出的操作放进线程池里,因为没有保证机制能够证明所有的线程池里正在运行或者还没运行的工作项能够具有明确的行为。
同步机制
ThreadPool没有提供简单的方法来获取工作线程已经结束,所以需要通过事件或者其他的内核对象来实现同步机制。1. 如果需要获取某一个工作线程是否结束可以使用手动事件来实现。
static private ManualResetEvent finish = new ManualResetEvent(false); static private void ThreadWorker(object state) { { for (int i = 0; i < 5; i++) { Thread.Sleep(1000); Console.WriteLine("current thead {0} wait for {1} seconds.", Thread.CurrentThread.ManagedThreadId, i + 1); } finish.Set(); } return; }主调函数实现代码为:
ThreadPool.QueueUserWorkItem(ThreadWorker); finish.WaitOne(); finish.Close();或者使用匿名委托函数加using关键字保证了事件的释放
using (ManualResetEvent finish = new ManualResetEvent(false)) { ThreadPool.QueueUserWorkItem(delegate { for (int i = 0; i < 5; i++) { Thread.Sleep(1000); Console.WriteLine("current thead {0} wait for {1} seconds.", Thread.CurrentThread.ManagedThreadId, i + 1); } finish.Set(); }); finish.WaitOne(); }
2.如果需要获取多个工作线程是否结束可以通过最后一个工作线程来触发事件来实现。
如果使用前面的方法给每一个工作线程分配一个事件,然后等待所有事件给触发,是非常低效的,可以使用如下方法
using (ManualResetEvent finish = new ManualResetEvent(false)) { int nTask = 10; for (int i = 0; i < nTask; i++) { ThreadPool.QueueUserWorkItem(delegate { for (int j = 0; j < 3; j++) { Thread.Sleep(1000); Console.WriteLine("current thead {0} wait for {1} seconds.", Thread.CurrentThread.ManagedThreadId, i * 10 + j + 1); } if (Interlocked.Decrement(ref nTask) == 0) { finish.Set(); } }, i); } finish.WaitOne(); }不过注意由于使用过了匿名委托所以i的值是不确定,有可能是1或者是10,所以为了改变这种情况不能使用匿名委托,
static private int _num = 10; static private ManualResetEvent finish = new ManualResetEvent(false); static private void ThreadWork(object state) { int i = (int)state; for (int j = 0; j < 3; j++) { Thread.Sleep(1000); Console.WriteLine("current thead {0} wait for {1} seconds.", Thread.CurrentThread.ManagedThreadId, i * 10 + j + 1); } if (Interlocked.Decrement(ref _num) == 0) finish.Set(); }主调函数实现代码为:
for (int i = 0; i < _num; i++) { ThreadPool.QueueUserWorkItem(ThreadWork, i); } finish.WaitOne(); finish.Close();
相关文章推荐
- C#多线程实现方法——线程池(Thread Pool)
- C#多线程实现方法——线程池(Thread Pool)
- [深入学习C#]C#实现多线程的方法:线程(Thread类)和线程池(ThreadPool)
- [深入学习C#]C#实现多线程的方法:线程(Thread类)和线程池(ThreadPool)
- spring ThreadPoolTaskExecutor的线程池类实现多线程
- Jetty的线程池实现QueuedThreadPool
- [叩响C#之门]写给初学者:多线程系列( 十一)——线程池(ThreadPool)
- C# 多线程 线程池(ThreadPool) 2 如何控制线程池?
- Java 实现多线程的3种方法:继承Thread类;实现Runnable接口;实现Callable接口。具体代码实现实例
- 高效线程池(threadpool)的实现
- 实现多线程有两种方法: Thread类继承和Runnable接口实现
- java多线程Thread的实现方法代码详解
- C#多线程--线程池(ThreadPool)
- Spring Boot使用@Async实现异步调用:ThreadPoolTaskScheduler线程池的优雅关闭
- ExecutorService常用方法和newFixedThreadPool创建固定大小的线程池
- python 线程池threadpool之实现
- 通过线程池使用多线程并发:ThreadPoolTaskExecutor 的应用例子
- ExecutorService常用方法和newFixedThreadPool创建固定大小的线程池
- 【源码剖析】threadpool —— 基于 pthread 实现的简单线程池
- Nodejs事件引擎libuv源码剖析之:高效线程池(threadpool)的实现