C#中怎么使用AutoResetEvent控制线程(autoresetevent,开发技术)

时间:2024-05-09 15:32:28 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

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();}}}

结果如下图所示:

C#中怎么使用AutoResetEvent控制线程

注意点:
不要有一点点点点多余的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++);}}}}

结果如下:

C#中怎么使用AutoResetEvent控制线程

第四种方法 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控制线程的详细内容,希望对您有所帮助,信息来源于网络。
上一篇:Golang中Interface接口的三个特性是什么下一篇:

8 人围观 / 0 条评论 ↓快速评论↓

(必须)

(必须,保密)

阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18