簡體   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