- // @ 来源于挽留刀的技术系列文章-C#的多线程机制探索
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
- using System.Threading;
- namespace MutiThread
- {
- /* 在多线程的程序中,经常会出现两种情况。一种情况下,应用程序中的线程
- * 把大部分的时间花费在等待状态,等待某个事件发生,然后才能给予响应;
- * 而另外一种情况则是线程平常都处于休眠状态,只是周期性地被唤醒。
- * 在.net framework里边,我们使用ThreadPool来对付第一种情况,使用Timer
- * 来对付第二种情况。本例就是ThreadPool的实例,Timer的实例参看Program4*/
- /* ThreadPool类也是一个静态类,你无需自己建立线程,只需把你要做的工作写
- * 成函数,然后作为参数传递给ThreadPool.QueueUserWorkItem()方法就行了,
- * 传递的方法就是依靠WaitCallback代理对象,而线程的建立、管理、运行等等
- * 工作都是由系统自动完成的,你无须考虑那些复杂的细节问题
- * 就好像你是公司老板——只需要安排工作,而不必亲自动手。*/
- //这是用来保存信息的数据结构,将作为参数被传递
- public class SomeState
- {
- public int Cookie;
- public SomeState(int iCookie)
- {
- Cookie = iCookie;
- }
- }
- public class Alpha
- {
- public Hashtable HashCount;
- // ManualResetEvent允许线程通过发信号互相通信,此通信涉及一个线程在其他线程进行之前必须完成的任务,相当于一个信号灯,可以利用它的信号来通知其它线程.
- public ManualResetEvent eventX;
- public static int iCount = 0;
- public static int iMaxCount = 0;
- public Alpha(int MaxCount)
- {
- HashCount = new Hashtable(MaxCount);
- iMaxCount = MaxCount;
- }
- // 线程池里的线程将调用Beta()方法
- public void Beta(Object state)
- {
- // 输出当前线程的hash编码值和Cookie的值
- Console.WriteLine(" {0} {1} :", Thread.CurrentThread.GetHashCode(), ((SomeState)state).Cookie);
- Console.WriteLine("HashCount.Count=={0}, Thread.CurrentThread.GetHashCode()=={1}", HashCount.Count, Thread.CurrentThread.GetHashCode());
- lock (HashCount)
- {
- // 如果当前的Hash表中没有当前线程的Hash值,则添加之
- if (!HashCount.ContainsKey(Thread.CurrentThread.GetHashCode()))
- {
- HashCount.Add(Thread.CurrentThread.GetHashCode(), 0);
- }
- HashCount[Thread.CurrentThread.GetHashCode()] = ((int)HashCount[Thread.CurrentThread.GetHashCode()]) + 1;
- }
- // 将当前线程挂起指定的时间
- int iX = 2000;
- Thread.Sleep(iX);
- /* Interlocked类为多个线程共享的变量提供原子操作,因为增加变量操作不
- * 是一个原子操作,可看成三个步骤来完成(可在msdn中Interlocked类的内容),
- * 以防当前线程在执行完前两个步骤后而被其他线程抢先 */
- // Interlocked.Increment()以原子操作的形式递增指定变量的值并存储结果
- Interlocked.Increment(ref iCount);
- if (iCount == iMaxCount)
- {
- Console.WriteLine();
- Console.WriteLine("Setting eventX ");
- // Set()将事件状态设置为终止状态,允许等待线程继续;Reset()将事件状态设置为非终止状态,从而导致等待线程线程受阻
- eventX.Set();
- }
- }
- }
- public class SimplePool
- {
- public static int Main(string[] args)
- {
- Console.WriteLine("Thread Pool Sample:");
- bool W2K = false;
- int MaxCount = 10;// 允许线程池中运行最多10个线程
- // 新建ManualResetEvent对象并且初始化为无信号状态
- ManualResetEvent eventX = new ManualResetEvent(false);
- Console.WriteLine("Queuing {0} items to Thread Pool", MaxCount);
- Alpha oAlpha = new Alpha(MaxCount); // 创建工作项
- // 注意初始化oAlpha对象的eventX属性
- oAlpha.eventX = eventX;
- Console.WriteLine("Queue to Thread Pool 0");
- try
- {
- // 将工作项装入线程池
- // 这里要用到Windows 2000以上版本才有的API,所以可能出现NotSupportException异常
- ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta),
- new SomeState(0));
- W2K = true;
- }
- catch (NotSupportedException)
- {
- Console.WriteLine("These API's may fail when called on a non-Windows 2000 system.");
- W2K = false;
- }
- if (W2K)// 如果当前系统支持ThreadPool的方法.
- {
- for (int iItem = 1; iItem < MaxCount; iItem++)
- {
- // 插入队列元素
- Console.WriteLine("Queue to Thread Pool {0}", iItem);
- ThreadPool.QueueUserWorkItem(new WaitCallback(oAlpha.Beta), new SomeState(iItem));
- }
- Console.WriteLine("Waiting for Thread Pool to drain");
- // 使当前主线程挂起,等待事件的完成,即线程调用ManualResetEvent.Set()方法
- eventX.WaitOne(Timeout.Infinite, true);
- // WaitOne()方法使调用它的线程等待直到eventX.Set()方法被调用
- Console.WriteLine("Thread Pool has been drained (Event fired)");
- Console.WriteLine();
- Console.WriteLine("Load across threads");
- foreach (object o in oAlpha.HashCount.Keys)
- {
- Console.WriteLine("{0} {1}", o, oAlpha.HashCount[o]);
- }
- }
- Console.ReadLine();
- return 0;
- }
- }
- }
多线程进阶代码三
最新推荐文章于 2023-05-31 18:37:54 发布