我试图了解AutoResetEvent和ManualResetEvent之间的区别。现在,我了解到AutoResetEvent允许一组线程中的每个线程一个接一个地工作。例如,您只有一台打印机,而您有两个打印任务,则希望打印任务1在打印任务2开始之前完成。在这种情况下,您将要使用AutoResetEvent。如果您想通过一个事件唤醒一堆线程,则ManualResetEvent很有用。
现在,我正在尝试使用以下代码片段来了解它们的工作原理。
static AutoResetEvent resetEvent = new AutoResetEvent(false);
static void Main(string[] args)
{
Task task = Task.Run(() =>
{
GetDataFromServer(1);
});
Task.Run(() =>
{
GetDataFromServer(2);
});
//Send first signal to get first set of data from server 1 and server 2
resetEvent.Set();
//manualResetEvent.Reset();
Thread.Sleep(TimeSpan.FromSeconds(2));
//Send second signal to get second set of data from server 1 and server 2
resetEvent.Set();
Console.ReadLine();
}
static void GetDataFromServer(int serverNumber)
{
//Calling any webservice to get data
Console.WriteLine("I get first data from server" + serverNumber);
resetEvent.WaitOne();
Thread.Sleep(TimeSpan.FromSeconds(2));
Console.WriteLine("I get second data from server" + serverNumber);
resetEvent.WaitOne();
Console.WriteLine("All the data collected from server" + serverNumber);
}
当我使用ManualResetEvent时,它会提供以下输出:
我从server1获得了第一笔数据
我从server2获得了第一笔数据
我从server1获得了第二个数据
从server1收集的所有数据
我从server2获得了第二个数据
从server2收集的所有数据
如果将ManualResetEvent更改为AutoResetEvent,则会得到不同的输出,并且“从服务器收集的所有数据”将永远不会打印出来:
我从server1获得了第一笔数据
我从server2获得了第一笔数据
我从server1获得了第二个数据
我从server2获得了第二个数据
似乎我仍然不太了解它们的工作原理。
问题:
为什么当我使用AutoResetEvent时,它们具有不同的输出,并且“从服务器收集的所有数据”语句从不打印出来?我调用Set()方法向线程发出信号,告知它们可以执行任务。
为什么在不调用reset()的情况下使用ManualResetEvent且输出与在reset()中使用的输出相同?
在使用AutoResetEvent和ManualResetEvent时,如何更改代码段以使其具有相同的输出?
答案 0 :(得分:0)
简要回答您的问题:
AutoResetEvent
在允许一个线程通过后自动重置。在上面的代码中,您要调用WaitOne()
四次,因此您需要进行四个相应的Set()
调用。这就是为什么您看不到最后的语句打印的原因。线程正在等待信号。
手动重置事件必须先手动重置,然后才能开始阻塞线程。 Set
方法释放所有等待的线程,然后在调用Reset
之前有一个完成的竞赛。如果这些线程实际上在Reset
之前完成,则结果将如指示。
您不能保证无论使用哪种行为,行为都是相同的。两者具有不同的行为,因此至少在某些时候将一个替换为另一个会产生不同的行为。