-
信号量:在C#多线程通信中主要用来向阻塞的线程传达信号从而使得阻塞线程继续执行。代表一种许可的概念,是否允许多线程对同一资源操作的许可。
-
多线程信号(线程交互):通常是指线程必须等待一个线程或者多个线程通知交互(释放信号),才可以继续执行。
-
在C#中信号量主要有这几个:
AutoResetEvent,
private static AutoResetEvent auto = new AutoResetEvent(false); Thread thread = new Thread(AutoReset);//定义线程去执行AutoReset方法 thread.Start();//开始线程 Thread.Sleep(5000);//休眠5s auto.Set(); static void AutoReset() { auto.WaitOne();//阻塞线程,等待释放信号从而继续执行下面的代码,一直等待 //auto.WaitOne(2000);//等待两秒,如果没有收到信号,则继续执行 Console.WriteLine("Wait 5s,Begin Run AutoReset"); }
ManualResetEvent,
private static ManualResetEvent manualResetEvent = new ManualResetEvent(false); { Thread thread = new Thread(ManualResetEvent);//定义线程去执行AutoReset方法 thread.Start();//开始线程 Thread.Sleep(5000);//休眠5s manualResetEvent.Set(); Thread.Sleep(5000); manualResetEvent.Reset();//和AutoResetEvent区别在于 AutoResetEvent会自动重置状态,ManualResetEvent需要手动Reset为无信号状态,否则二次或者多次waitone无效 } static void ManualResetEvent() { manualResetEvent.WaitOne();//阻塞线程,等待释放信号从而继续执行下面的代码,一直等待 //auto.WaitOne(2000);//等待两秒,如果没有收到信号,则继续执行 Console.WriteLine("Wait 5s,Begin Run manualResetEvent"); }
CountdownEvent,
var CountdownEvent = new CountdownEvent(1000); //CountdownEvent.CurrentCount//当前总数 //CountdownEvent.AddCount()//添加1 //CountdownEvent.AddCount(10);//添加指定数量 //CountdownEvent.InitialCount//总数 //CountdownEvent.Reset()//设置为InitialCount初始值 //CountdownEvent.Reset(100)//设置为指定初始值 Task.Run(() => { for (int i = 0; i < 1000; i++) { Task.Delay(100); CountdownEvent.Signal();//代表计数器-1 Console.WriteLine(CountdownEvent.CurrentCount); } }); CountdownEvent.Wait();//等待计数器归0 Console.WriteLine("结束");
EventWaitHandle,
#region 同AutoResetEvent Thread thread = new Thread(EventWaitHandleAutoReset);//定义线程去执行AutoReset方法 thread.Start();//开始线程 Thread.Sleep(5000);//休眠5s eventWaitHandle.Set();//如果下方调用SignalAndWait则可以此处注释掉 #endregion #region ManualResetEvent thread = new Thread(EventWaitHandleManualReset);//定义线程去执行AutoReset方法 thread.Start();//开始线程 //Thread.Sleep(5000);//休眠5s //eventWaitHandleManualReset.Set();同ManualReset一样 下方方法之所以Set 因为下面发了一个信号,并且等待了一个线程, WaitHandle.SignalAndWait(eventWaitHandle, eventWaitHandleManualReset);//eventWaitHandle发出信号Set,eventWaitHandleManualReset阻塞线程等待信号,EventWaitHandleManualReset发出信号后可以执行Console。WriteLine,否则一直阻塞 Console.WriteLine(); #endregion static void EventWaitHandleAutoReset() { eventWaitHandle.WaitOne();//阻塞线程,等待释放信号从而继续执行下面的代码,一直等待 //auto.WaitOne(2000);//等待两秒,如果没有收到信号,则继续执行 Console.WriteLine("Wait 5s,Begin Run EventWaitHandle AutoReset"); Thread.Sleep(5000); } static void EventWaitHandleManualReset() { Thread.Sleep(5000);//休眠5s等待SignalAndWait阻塞线程,此处释放 eventWaitHandleManualReset.Set(); //eventWaitHandleManualReset.WaitOne();//阻塞线程,等待释放信号从而继续执行下面的代码,一直等待 //auto.WaitOne(2000);//等待两秒,如果没有收到信号,则继续执行 Console.WriteLine("Wait 5s,Begin Run EventWaitHandle ManualReset"); }
Semaphore
private static Semaphore Semaphore = new Semaphore(3, 3); for (int i = 0; i <= 10; i++) { Thread thread = new Thread(new ParameterizedThreadStart(SemaphoreTest)); thread.Start(i); } Semaphore.WaitOne();//阻塞线程,等待计数器小于设置的初始值后可以进入 Console.WriteLine(state + "进入了资源"); Thread.Sleep((int)state * 1000); Semaphore.Release();//释放信号,计数器+1 Console.WriteLine(state + "离开了了资源"
-
非终止状态(无信号):线程受阻 终止状态线程执行(有信号):线程执行
-
Sleep函数:让当前线程暂停执行一段时间,通常用于模拟实际运行环境下的等待或延时操作。
Thread.Sleep(0):指定零 (0) 以指示应挂起此线程以使其他等待线程能够执行。并非是真的要线程挂起0毫秒,意义在于这次调用Thread.Sleep(0)的当前线程确实的被冻结了一下,让其他线程有机会优先执行。Thread.Sleep(0) 是你的线程暂时放弃cpu,也就是释放一些未用的时间片给其他线程或进程使用,就相当于一个让位动作。
C#多线程通信
于 2023-10-07 17:45:53 首次发布