ManualResetEvent 和 AutoResetEvent
从字面意思看,它们都表示是一个事件(Event)。这两个类都有WaitOne方法,这个方法被调用后,当前的线程(即是调用这个方法的线程)暂停运行(可以看做等待事件触发),直到事件被触发(即另外的线程调用了它的Set方法)
ManualReset说明这个事件被触发后(Set方法被调用),是要手工进行重置的(即调用Reset方法),否则再次调用它的WaitOne方法是没有用的(也就是调用WaitOne的线程不会停下等待事件触发,而是继续执行)。它提供手工重置的方法是调用Reset方法。
AutoResetEvent则是Set被调用后,如果WaitOne再次被调用,当前的线程还是会被暂停的,也就是不用手工调用它的Reset方法,就能使WaitOne再次生效。
看下面几个示例
namespace Demo
{
[TestClass]
public class ThreadDemo
{
[TestMethod]
public void ThreadTest()
{
Thread thread1 = new Thread(new ThreadStart(Print));
thread1.Start();
}
public void Print()
{
Thread.Sleep(1000);
Console.WriteLine("Print.....");
}
}
上面这个示例的输出为空。因为thread1.Start()后,线程继续运行结束。而Print()方法中因为有Thread.Sleep(1000),所以Console.WriteLine("Print.....");还没来得及运行,主线程就结束了。
怎么让主线程等待呢。可以通过ManualResetEvent 或 AutoResetEvent的WaitOne()方法。见下面的示例
namespace Demo
{
[TestClass]
public class ThreadDemo
{
private ManualResetEvent manualResetEvent;
[TestMethod]
public void ThreadTest()
{
manualResetEvent = new ManualResetEvent(false);
Thread thread1 = new Thread(new ThreadStart(Print));
thread1.Start();
manualResetEvent.WaitOne();
}
public void Print()
{
Thread.Sleep(1000);
Console.WriteLine("Print.....");
manualResetEvent.Set();
}
}
上面的示例输出为: "Print.....". 因为主线程中调用了manualResetEvent.WaitOne(),它一定要等到Print()方法中的manualResetEvent.Set()执行完后才能继续往下进行。
将ManualResetEvent 换成AutoResetEvent也能达到上面一样的效果,见下例。
namespace Demo
{
[TestClass]
public class ThreadDemo
{
private AutoResetEvent autoResetEvent;
[TestMethod]
public void ThreadTest()
{
autoResetEvent = new AutoResetEvent(false);
Thread thread1 = new Thread(new ThreadStart(Print));
thread1.Start();
autoResetEvent.WaitOne();
}
public void Print()
{
Thread.Sleep(1000);
Console.WriteLine("Print.....");
autoResetEvent.Set();
}
}
输出也是: "Print....."。
下面的示例演示AutoResetEvent调用过Set方法后,再次调用WaitOne还是有用的
namespace Demo
{
[TestClass]
public class ThreadDemo
{
private AutoResetEvent autoResetEvent;
[TestMethod]
public void ThreadTest()
{
autoResetEvent = new AutoResetEvent(false);
Thread thread1 = new Thread(new ThreadStart(Print));
thread1.Start();
autoResetEvent.WaitOne();
thread1 = new Thread(new ThreadStart(Print));
thread1.Start();
autoResetEvent.WaitOne();
}
public void Print()
{
Thread.Sleep(1000);
Console.WriteLine("Print.....");
autoResetEvent.Set();
}
}
输出为:
Print.....
Print.....
而下面的示例演示ManualResetEvent调用过Set方法后,再次调用WaitOne是无效的,必须先调用Reset方法
namespace Demo
{
[TestClass]
public class ThreadDemo
{
private ManualResetEvent manualResetEvent;
[TestMethod]
public void ThreadTest()
{
manualResetEvent = new ManualResetEvent(false);
Thread thread1 = new Thread(new ThreadStart(Print));
thread1.Start();
manualResetEvent.WaitOne();
thread1 = new Thread(new ThreadStart(Print));
thread1.Start();
manualResetEvent.WaitOne();
}
public void Print()
{
Thread.Sleep(1000);
Console.WriteLine("Print.....");
manualResetEvent.Set();
}
}
输出为: “Print.....”。