AutoResetEvent
是.net线程简易同步方法中的一种。AutoResetEvent
常常被用来在两个线程之间进行信号发送
两个线程共享相同的AutoResetEvent对象,线程可以通过调用AutoResetEvent对象的WaitOne()
方法进入等待状态,然后另外一个线程通过调用AutoResetEvent对象的Set()
方法取消等待的状态。
AutoResetEvent如何工作的?
在内存中保持着一个bool值,如果bool值为False,则使线程阻塞,反之,如果bool值为True,则使线程退出阻塞。当我们创建AutoResetEvent对象的实例时,我们在函数构造中传递默认的bool值,以下是实例化AutoResetEvent的例子。
AutoResetEvent autoResetEvent = new AutoResetEvent(false);
WaitOne 方法
该方法阻止当前线程继续执行,并使线程进入等待状态以获取其他线程发送的信号。WaitOne
将当前线程置于一个休眠的线程状态。WaitOne
方法收到信号后将返回True,否则将返回False。
autoResetEvent.WaitOne();
WaitOne
方法的第二个重载版本是等待指定的秒数。如果在指定的秒数后,没有收到任何信号,那么后续代码将继续执行。
static void ThreadMethod()
{
while(!autoResetEvent.WaitOne(TimeSpan.FromSeconds(2)))
{
Console.WriteLine("Continue");
Thread.Sleep(TimeSpan.FromSeconds(1));
}
Console.WriteLine("Thread got signal");
}
这里我们传递了2秒钟作为WaitOne
方法的参数。在While循环中,autoResetEvent
对象等待2秒,然后继续执行。当线程取得信号,WaitOne
返回为True,然后退出循环,打印"Thread got signal"的消息。
Set 方法
AutoResetEvent Set()
方法发送信号到等待线程以继续其工作,以下是调用该方法的格式。
autoResetEvent.Set();
AutoResetEvent例子
下面的例子展示了如何使用AutoResetEvent来释放线程。在Main方法中,我们用Task Factory创建了一个线程,它调用了GetDataFromServer
方法。调用该方法后,我们调用AutoResetEvent
的WaitOne
方法将主线程变为等待状态。在调用GetDataFromServer
方法时,我们调用了AutoResetEvent
对象的Set
方法,它释放了主线程,并控制台打印输出dataFromServer
方法返回的数据。
class Program
{
static AutoResetEvent autoResetEvent = new AutoResetEvent(false);
static string dataFromServer = "";
static void Main(string[] args)
{
Task task = Task.Factory.StartNew(() =>
{
GetDataFromServer();
});
//Put the current thread into waiting state until it receives the signal 主线程变为阻塞状态
autoResetEvent.WaitOne();
//Thread got the signal
Console.WriteLine(dataFromServer);
}
static void GetDataFromServer()
{
//Calling any webservice to get data
Thread.Sleep(TimeSpan.FromSeconds(4));
dataFromServer = "Webservice data";
autoResetEvent.Set();
}
}
总结一下:
Set():
此方法将ManualResetEvent设置为已触发状态,这将导致所有等待的线程被释放并继续执行。如果之前没有线程在等待,则此方法没有任何效果。
Reset():
此方法将ManualResetEvent重置为初始状态,即将其设置为未触发状态。在调用Set()之前,任何等待的线程都将被阻塞,直到再次调用Set()或Reset()。
WaitOne():
此方法将当前线程置于等待状态,直到ManualResetEvent被设置为已触发状态。当Set()被调用时,等待的线程将被释放并继续执行。如果ManualResetEvent当前处于未触发状态,则此方法将阻塞当前线程,直到它被设置为已触发状态。