1.了解信号
在这两个信号中:
1.Set方法可以将信号置为发送状态;
释放信号,所有等待信号的线程都将获得信号,开始执行WaitOne()后面的语句;
将事件状态设置为中,终止状态许一个或多个的等待线程继续
2.Reset方法将信号置为不发送状态:
一旦我们调用了ManualResetEvent对象的Set()方法,它的bool值就变为true,我们可以调用Reset()方法来重置该值,Reset()方法重置该值为False
3.WaitOne等待信号的发送(在需要等待信号的线程中调用WaitOne方法,该方法会阻塞当前线程,直到收到信号);该方法阻塞当前线程并等待其他线程发送信号。如果收到信号,它将返回True,反之返回False。
多个线程可以通过调用ManualResetEvent对象的WaitOne方法进入等待或阻塞状态。当控制线程调用Set()方法,所有等待线程将恢复并继续执行。
我们可以通过构造函数的参数值来决定其初始状态,若为true则非阻塞状态,为false为阻塞状态。如果某个线程调用WaitOnef方法,则当信号处于发送状态时,线程会得到信号,继续向下执行。
2.ManualResetEvent——可以对所有进行等待的线程进行统一控制
2.1 ManualResetEvent是如何工作的
在内存中保持着一个bool值,如果bool值为False,则使所有线程阻塞,反之,如果bool值为True,则使所有线程退出阻塞。当我们创建ManualResetEvent对象的实例时,我们在函数构造中传递默认的bool值。
ManualResetEvent manualResetEvent = new ManualResetEvent(false);
在上面代码中,我们初始化了一个值为False的ManualResetEvent对象,这意味着所有调用WaitOne放的线程将被阻塞,直到有线程调用了 Set() 方法。而如果我们用值True来对ManualResetEvent对象进行初始化,所有调用WaitOne方法的线程并不会被阻塞,可以进行后续的执行。
2.2 如何使用
class Program { static void Main(string[] args) { //注意:ManualResetEvent可以对所有进行等待的线程进行统一控制 //true-初始状态为发出信号;false-初始状态为未发出信号 ManualResetEvent mre = new ManualResetEvent(false); //线程池开启10个线程 for (int i = 0; i < 10; i++) { int k = i; ThreadPool.QueueUserWorkItem(t => { Console.WriteLine($"这是第{k+1}个线程,线程ID为{Thread.CurrentThread.ManagedThreadId}"); //等待信号,没有信号的话不会执行后面的语句,因为初始状态是false,所以后面的语句暂时不会执行 mre.WaitOne(); Console.WriteLine($"第{k+1}个线程获得信号,线程ID为{Thread.CurrentThread.ManagedThreadId}"); }); } Thread.Sleep(5000); Console.WriteLine("\r\n 5秒后发出信号... \r\n"); //Set()方法:释放信号,所有等待信号的线程都将获得信号,开始执行WaitOne()后面的语句 mre.Set(); Console.ReadKey(); } }
执行结果如图:
可见,没有信号时,WaitOne()后面的语句都不执行(被阻塞),当Set()释放信号后,所有阻塞的线程都开始继续执行。
原文链接:https://blog.csdn.net/u013986317/article/details/87909603原文:http://www.cnblogs.com/li-peng/p/3291306.html