繁体   English   中英

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

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

我试图了解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获取第二个数据

好像我还是不太了解它们是如何工作的。

题:

  1. 为什么它们具有不同的输出,并且当我使用AutoResetEvent时,“从服务器收集的所有数据”语句从不打印出来? 我调用Set()方法来向线程发出信号,告知他们可以执行任务。

  2. 在不调用reset()的情况下使用ManualResetEvent且输出与在reset()中使用的输出相同时,怎么办?

  3. 使用AutoResetEvent和ManualResetEvent时,如何更改代码段以使其具有相同的输出?

对您问题的简要回答:

  1. AutoResetEvent让一个线程通过后自动重置。 在上面的代码中,您要四次调用WaitOne() ,因此您需要进行四个相应的Set()调用。 这就是为什么您看不到最后的语句打印的原因。 线程正在等待信号。

  2. 手动重置事件必须先手动重置,然后才能开始阻塞线程。 Set方法释放所有等待的线程,然后在调用Reset之前需要完成一个竞赛。 如果这些线程实际上在Reset之前完成,则结果将如所示。

  3. 您不能保证无论使用哪种行为,行为都是相同的。 两者具有不同的行为,因此至少在某些时候将一个替换为另一个会产生不同的行为。

暂无
暂无

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

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