C#中怎么使用AutoResetEvent控制线程
导读:本文共3272字符,通常情况下阅读需要11分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: AutoResetEvent主要方法及实践AutoResetEvent(bool initialState):构造函数,用一个指示是否将初始状态设置为终止的布尔值初始化该类的新实例。 false:无信号,子线程的WaitOne方法不会被自动调用 true:有信号,子线程的WaitOne方法会被自动调用Reset ():将事件状态设置为非终止状态,导致线程阻止;如... ...
目录
(为您整理了一些要点),点击可以直达。AutoResetEvent主要方法及实践
AutoResetEvent(bool initialState):构造函数,用一个指示是否将初始状态设置为终止的布尔值初始化该类的新实例。 false:无信号,子线程的WaitOne方法不会被自动调用 true:有信号,子线程的WaitOne方法会被自动调用
Reset ():将事件状态设置为非终止状态,导致线程阻止;如果该操作成功,则返回true;否则,返回false。
Set ():将事件状态设置为终止状态,允许一个或多个等待线程继续;如果该操作成功,则返回true;否则,返回false。
WaitOne(): 阻止当前线程,直到收到信号。
WaitOne(TimeSpan, Boolean) :阻止当前线程,直到当前实例收到信号,使用 TimeSpan 度量时间间隔并指定是否在等待之前退出同步域。
有了上面的解释,开始展示代码(经过多次优化)
//若要将初始状态设置为终止,则为true;若要将初始状态设置为非终止,则为falsestaticAutoResetEventoddResetEvent=newAutoResetEvent(false);staticAutoResetEventevenResetEvent=newAutoResetEvent(false);staticinti=0;staticvoidMain(string[]args){//ThreadStart是个委托Threadthread1=newThread(newThreadStart(show));thread1.Name="偶数线程";Threadthread2=newThread(newThreadStart(show));thread2.Name="奇数线程";thread1.Start();Thread.Sleep(2);//保证偶数线程先运行。thread2.Start();Console.Read();}publicstaticvoidshow(){while(i<=100){intnum=i%2;if(num==0){Console.WriteLine("{0}:{1}{2}",Thread.CurrentThread.Name,i++,"evenResetEvent");if(i!=1)evenResetEvent.Set();oddResetEvent.WaitOne();//当前线程阻塞}else{Console.WriteLine("{0}:{1}{2}",Thread.CurrentThread.Name,i++,"oddResetEvent");//如果此时AutoResetEvent为非终止状态,则线程会被阻止,并等待当前控制资源的线程通过调用Set来通知资源可用。否则不会被阻止oddResetEvent.Set();evenResetEvent.WaitOne();}}}
结果如下图所示:
注意点:
不要有一点点点点多余的evenResetEvent.Set(),他会让后续的 evenResetEvent.WaitOne();失效.
第二种方法Semaphore
此外,我们利用信号量也可以实现,信号量是一种内核模式锁,对性能要求比较高,特殊情况下才考虑使用,而且要避免在内核模式和用户模式下频繁相互切换线程。代码如下:
privatestaticreadonlyintMaxSize=1;privatestaticinti=0;staticSemaphoreoddSemaphore=newSemaphore(0,MaxSize);staticSemaphoreevenSemaphore=newSemaphore(0,MaxSize);staticvoidMain(string[]args){System.Diagnostics.Stopwatchstopwatch=newSystem.Diagnostics.Stopwatch();stopwatch.Start();//ThreadStart是个委托Threadthread1=newThread(newThreadStart(show));thread1.Name="偶数线程";Threadthread2=newThread(newThreadStart(show));thread2.Name="奇数线程";thread1.Start();thread2.Start();thread1.Join();stopwatch.Stop();Console.WriteLine(stopwatch.Elapsed.TotalMilliseconds);Console.Read();}privatestaticvoidshow(){if(i==1)evenSemaphore.WaitOne();while(i<=100){intnum=i%2;if(num==0){Console.WriteLine("{0}:{1}{2}",Thread.CurrentThread.Name,i++,Thread.CurrentThread.ManagedThreadId);evenSemaphore.Release();oddSemaphore.WaitOne();//当前线程阻塞}else{Console.WriteLine("{0}:{1}{2}",Thread.CurrentThread.Name,i++,Thread.CurrentThread.ManagedThreadId);//释放一个偶数信号空位出来;oddSemaphore.Release();evenSemaphore.WaitOne();//当前线程阻塞//此时已经消耗了一个奇数信号空位}}}
第三种方法,约定每个线程只干自己的事
这种方法利用线程池本身就是队列的方式,即先进先出。测试之后发现性能有下降,但是还是贴出来供参考。
staticintthreadCount=2;staticintcount=0;staticobjectcursorLock=newobject();staticvoidMain(string[]args){System.Diagnostics.Stopwatchstopwatch=newSystem.Diagnostics.Stopwatch();stopwatch.Start();Task[]arr=newTask[2];for(intthreadIndex=0;threadIndex<threadCount;threadIndex++){//这两种方法都可以arr[threadIndex]=Task.Factory.StartNew(PrintNum,threadIndex);}Task.WaitAll(arr);stopwatch.Stop();Console.WriteLine(stopwatch.Elapsed.TotalMilliseconds);Console.Read();}privatestaticvoidPrintNum(objectnum){boolisOk=false;while(!isOk){lock(cursorLock){intindex=count%2;if(count>100){isOk=true;}elseif(index==(int)num){if(index==0)Console.WriteLine("{0}:{1}{2}","偶数线程",Thread.CurrentThread.ManagedThreadId,count++);elseConsole.WriteLine("{0}:{1}{2}","奇数线程",Thread.CurrentThread.ManagedThreadId,count++);}}}}
结果如下:
第四种方法 Mutex
privatestaticinti=0;staticMutexmutex=newMutex();staticvoidMain(string[]args){System.Diagnostics.Stopwatchstopwatch=newSystem.Diagnostics.Stopwatch();stopwatch.Start();//ThreadStart是个委托Threadthread1=newThread(newParameterizedThreadStart(show));thread1.Name="偶数线程";Threadthread2=newThread(newParameterizedThreadStart(show));thread2.Name="奇数线程";thread1.Start(0);thread2.Start(1);thread2.Join();stopwatch.Stop();Console.WriteLine(stopwatch.Elapsed.TotalMilliseconds);Console.Read();}///<summary>///Mutex的释放与锁定都只能在同一个线程中执行///</summary>privatestaticvoidshow(objectindex){while(i<=100){mutex.WaitOne();intnum=i%2;if(num==(int)index&&i<=100){Console.WriteLine("{0}:{1}{2}",Thread.CurrentThread.Name,i++,Thread.CurrentThread.ManagedThreadId);}mutex.ReleaseMutex();}}
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
C#中怎么使用AutoResetEvent控制线程的详细内容,希望对您有所帮助,信息来源于网络。