简体   繁体   English

为什么在C#中使用AutoResetEvent和ManualResetEvent时,我的代码输出为何不同?

[英]Why the outputs of my code is difference when using AutoResetEvent and ManualResetEvent in C#

I'm trying to understand the difference between AutoResetEvent and ManualResetEvent. 我试图了解AutoResetEvent和ManualResetEvent之间的区别。 Right now I understand that the AutoResetEvent lets each thread in a group of threads to do their works one by one. 现在,我了解到AutoResetEvent允许一组线程中的每个线程一个接一个地工作。 For instance, you have only one printer and you have two print tasks, you want print task 1 to finish before print task 2 start. 例如,您只有一台打印机,而您有两个打印任务,则希望打印任务1在打印任务2开始之前完成。 In this situation, you will want to use AutoResetEvent. 在这种情况下,您将要使用AutoResetEvent。 A ManualResetEvent is useful if you want to wake up a bunch of threads with a single event. 如果您想通过单个事件唤醒一堆线程,则ManualResetEvent很有用。

Right now I'm trying to use the following code snippet to understand how they work. 现在,我正在尝试使用以下代码片段来了解它们的工作原理。

    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);
    }

When I use the ManualResetEvent, it gives me the following output: 当我使用ManualResetEvent时,它会提供以下输出:

I get first data from server1 我从server1获得了第一笔数据

I get first data from server2 我从server2获取了第一笔数据

I get second data from server1 我从server1获取第二个数据

All the data collected from server1 从server1收集的所有数据

I get second data from server2 我从server2获取第二个数据

All the data collected from server2 从server2收集的所有数据

If I change the ManualResetEvent to AutoResetEvent, I get different output and the "All the data collected from server" never print out: 如果将ManualResetEvent更改为AutoResetEvent,则会得到不同的输出,并且“从服务器收集的所有数据”将永远不会打印出来:

I get first data from server1 我从server1获得了第一笔数据

I get first data from server2 我从server2获取了第一笔数据

I get second data from server1 我从server1获取第二个数据

I get second data from server2 我从server2获取第二个数据

Seems like I still not fully understand how they work. 好像我还是不太了解它们是如何工作的。

Question: 题:

  1. Why they have different outputs and the "All the data collected from server" statement never print out when I use the AutoResetEvent? 为什么它们具有不同的输出,并且当我使用AutoResetEvent时,“从服务器收集的所有数据”语句从不打印出来? I call the Set() method to signal threads that they can perform their tasks. 我调用Set()方法来向线程发出信号,告知他们可以执行任务。

  2. How come when I use the ManualResetEvent without calling the reset() and the output is the same as using it with the reset()? 在不调用reset()的情况下使用ManualResetEvent且输出与在reset()中使用的输出相同时,怎么办?

  3. How can I change the code snippet to make it have the same output when using AutoResetEvent and ManualResetEvent? 使用AutoResetEvent和ManualResetEvent时,如何更改代码段以使其具有相同的输出?

Brief answers to your questions: 对您问题的简要回答:

  1. AutoResetEvent resets automatically after it lets one thread through. AutoResetEvent让一个线程通过后自动重置。 In the code above, you are calling WaitOne() four times, so you would need to have four corresponding Set() calls. 在上面的代码中,您要四次调用WaitOne() ,因此您需要进行四个相应的Set()调用。 That's why you aren't seeing the last statements print; 这就是为什么您看不到最后的语句打印的原因。 the threads are waiting for the signal. 线程正在等待信号。

  2. A manual reset event must be manually reset before it will begin blocking threads. 手动重置事件必须先手动重置,然后才能开始阻塞线程。 The Set method releases all waiting threads, then there is then a race to finish before Reset is called. Set方法释放所有等待的线程,然后在调用Reset之前需要完成一个竞赛。 If those threads actually finish before Reset , your results will be as indicated. 如果这些线程实际上在Reset之前完成,则结果将如所示。

  3. You cannot guarantee behavior will be the same regardless which one is used. 您不能保证无论使用哪种行为,行为都是相同的。 The two have different behaviors, so substituting one for the other will yield different behavior at least some of the time. 两者具有不同的行为,因此至少在某些时候将一个替换为另一个会产生不同的行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM