首頁 後端開發 C#.Net教程 .NET 同步與非同步 之 EventWaitHandle

.NET 同步與非同步 之 EventWaitHandle

Apr 11, 2017 pm 02:05 PM


在前一篇我們已經提到Mutex和本篇的主角們直接或間接繼承自WaitHandle:

陣列

裡的所有成員。於控制等待逾時的重載方法,請自行參考。返回。

執行緒相關性
  • #Mutex與Monitor一樣,是具有執行緒相關性的。到過,只有透過Monitor.Enter()/TryEnter()獲得物件鎖定的執行緒才能呼叫Pulse()/Wait()/Exit();同樣的,只有獲得Mutex擁有權的執行緒才能執行ReleaseMutex()方法,否則就會引發異常。這就是所謂的線程相關性。

  • 相反,EventWaitHandle以及它的衍生類別AutoResetEvent和ManualResetEvent都是線程無關的。任何執行緒都可以發送訊號給EventWaitHandle,喚醒阻塞在上面的執行緒。
  • 下一篇要提到的Semaphore也是線程無關的。

  •  
  • Event通知

EventWaitHandle、AutoResetEvent、ManualResetEvent名字裡都有一個“Event”,不過這跟. net的本身的

事件

機製完全沒有關係,它不涉及任何委託或事件處理程式。相對於我們之前碰到的Monitor和Mutex需要執行緒去爭奪「鎖」而言,我們可以把它們理解為一些需要執行緒等待的「事件」。線程透過等待這些事件的“發生”,把自己阻塞起來。一旦「事件」完成,被阻塞的執行緒在收到訊號後就可以繼續工作。

      為了配合WaitHandle上的3個靜態方法SingnalAndWait()/WailAny()/WaitAll(),EventWaitHandle提供了自己獨有的,使「Event」完成和重新開始的方法:
  • bool:Set():英文版MSDN:Sets the state of the event to signaled, allowing one or more waiting threads to proceed;中文版MSDN:將事件
  • 狀態
  • 設定為終止狀態,允許一個或多個等待執行緒繼續。初看「signaled」和「終止」似乎不對應,細想起來這兩者的說法其實也不矛盾。事件如果在進行中,當然就沒有“終止”,那麼

    其它

    線程就需要等待;一旦事件完成,那麼事件就“終止”了,於是我們發送信號喚醒等待的線程,所以“信號已發送”狀態也是合理的。兩個小細節:
  1. 無論中文或英文版,都提到這個方法都是可以讓「一個」或「多個」等待執行緒「繼續/Proceed」(注意不是「喚醒」)。所以這個方法在「喚醒」這個動作上是類似Monitor.Pulse()和Monitor.PulseAll()的。至於什麼時候類似Pulse(),又在什麼時候類似PulseAll(),往下看。

  2. 這個方法有bool型的回傳值:如果該操作成功,則為true;否則,為false。不過MSDN並沒有告訴我們,什麼時候執行會失敗,你只有找微軟MVP問了。

  • bool:Reset():Sets the state of the event to nonsignaled, causing threads to block. 將事件狀態設為非終止狀態,導致執行緒封鎖。 同樣,我們需要明白「nonsignaled」和「非終止」是一回事。同樣的是,仍然有個無厘頭的回傳值。 Reset()的作用,相當於讓事件重新開始處於“進行中”,那麼此後所有WaitOne()/WaitAll()/WaitAny()/SignalAndWait()這個事件的線程都會再次被擋在門外。

  •  

    建構子

    來看看EventWaitHandle眾多建構子中最簡單的一個:

    • EventWaitHandle(Boolean initialState, EventResetMode mode):初始化EventWaitHandle類別的新實例,並指定等待句柄最初是否處於終止狀態,以及它是自動重置還是手動重置。大多數時候我們會在第一個參數裡使用false,這樣新實例會缺省為「非終止」狀態。第二個參數EventResetMode是個列舉,總共兩個值:

    1. EventResetMode.AutoReset:當Set()被呼叫目前EventWaitHandle轉入終止狀態時,若有執行緒阻塞在目前EventWaitHandle上,那麼在釋放一個執行緒後EventWaitHandle就會自動重置(相當於自動呼叫Reset())再次轉入非終止狀態,剩餘的原來阻塞的線程(如果有的話)還會繼續阻塞。如果呼叫Set()後本沒有執行緒阻塞,那麼EventWaitHandle將保持「終止」狀態直到一個執行緒嘗試等待該事件,而這個執行緒不會被阻塞,此後EventWaitHandle才會自動重置並阻塞那之後的所有執行緒。

    2. EventResetMode.ManualReset:當終止時,EventWaitHandle 釋放所有等待的線程,並在手動重置前,即Reset()被呼叫前,一直保持終止狀態。

      好了,現在我們可以清楚的知道Set()在什麼時候分別類似於Monitor.Pulse()/PulseAll()了:

    • #當EventWaitHandle工作在AutoReset模式下,就喚醒功能而言,Set()與Monitor.Pulse()類似。此時,Set()只能喚醒眾多(如果有多個的話)被阻塞執行緒中的一個。但兩者仍有些差別:

    1. Set()的作用不僅僅是“喚醒”而是“釋放”,可以讓執行緒繼續工作(proceed);相反, Pulse()喚醒的執行緒只是重新進入Running狀態,參與物件鎖定的爭奪,誰都不能保證它一定會獲得物件鎖定。

    2. Pulse()的已被呼叫的狀態不會被維護。因此,如果在沒有等待執行緒時呼叫Pulse(),那麼下一個呼叫Monitor.Wait()的執行緒仍然會被阻塞,就像Pulse() 沒有被呼叫過。也就是說Monitor.Pulse()只在呼叫當時發揮作用,並不像Set()的作用會持續到下一個WaitXXX()。

  • 在一個工作在ManualReset模式下的EventWaitHandle的Set()方法被呼叫時,它所扮演的喚醒作用與Monitor.PulseAll()類似,所有被阻塞的執行緒都會收到訊號被喚醒。而兩者的差異與上面完全相同。

  •   來看看EventWaitHandle的其它建構子:

    • EventWaitHandle(Boolean initialState, EventResetMode mode, String name):前兩個參數我們已經看過,第三個參數name用於在系統範圍內指定同步事件的名稱。是的,正如我們在Mutex一篇中提到的,由於父類WaitHandle是具有跨進程域的能力的,因此跟Mutex一樣,我們可以創建一個全域的EventWaitHandle,讓後將它用於進程間的通知。注意,name仍然是大小寫敏感的,仍然有命名前綴的問題跟,你可以參考這裡。當name為null或空字串時,這等效於建立一個局部的未命名的EventWaitHandle。仍然同樣的還有,可能會因為已經系統中已經有同名的EventWaitHandle而只回傳一個實例表示同名的EventWaitHandle。所以最後仍舊同樣地,如果你需要知道這個EventWaitHandle是否由你最早創建,你需要使用以下兩個建構函式之一。

    • EventWaitHandle(Boolean initialState, EventResetMode mode, String name, out Boolean createdNew):createdNew用來表示是否成功建立了EventWaitHandle,true表示成功,false表示已經存在同名的事件。

    • EventWaitHandle(Boolean initialState, EventResetMode mode, String name, out Boolean createdNew, EventWaitHandleSecurity):關於安全的問題,直接查看這個建構子上的範例吧。全域MutexEventWaitHandle的安全性問題應該相對Mutex更需要注意,因為有可能駭客程式用相同的事件名稱對你的執行緒發送訊號或進行組織,那樣可能會嚴重危害你的業務邏輯。

     

    MSDN Demo


    #
    using System;using System.Threading;public class Example
    {    // The EventWaitHandle used to demonstrate the difference    // between AutoReset and ManualReset synchronization events.    //    private static EventWaitHandle ewh;    // A counter to make sure all threads are started and    // blocked before any are released. A Long is used to show    // the use of the 64-bit Interlocked methods.    //    private static long threadCount = 0;    // An AutoReset event that allows the main thread to block    // until an exiting thread has decremented the count.    //    private static EventWaitHandle clearCount = 
            new EventWaitHandle(false, EventResetMode.AutoReset);
    
        [MTAThread]    public static void Main()
        {        // Create an AutoReset EventWaitHandle.        //        ewh = new EventWaitHandle(false, EventResetMode.AutoReset);        // Create and start five numbered threads. Use the        // ParameterizedThreadStart delegate, so the thread        // number can be passed as an argument to the Start 
            // method.
            for (int i = 0; i <= 4; i++)
            {
                Thread t = new Thread(                new ParameterizedThreadStart(ThreadProc)
                );
                t.Start(i);
            }        // Wait until all the threads have started and blocked.        // When multiple threads use a 64-bit value on a 32-bit        // system, you must access the value through the        // Interlocked class to guarantee thread safety.        //        while (Interlocked.Read(ref threadCount) < 5)
            {
                Thread.Sleep(500);
            }        // Release one thread each time the user presses ENTER,        // until all threads have been released.        //        while (Interlocked.Read(ref threadCount) > 0)
            {
                Console.WriteLine("Press ENTER to release a waiting thread.");
                Console.ReadLine();            // SignalAndWait signals the EventWaitHandle, which            // releases exactly one thread before resetting, 
                // because it was created with AutoReset mode. 
                // SignalAndWait then blocks on clearCount, to 
                // allow the signaled thread to decrement the count            // before looping again.            //            WaitHandle.SignalAndWait(ewh, clearCount);
            }
            Console.WriteLine();        // Create a ManualReset EventWaitHandle.        //        ewh = new EventWaitHandle(false, EventResetMode.ManualReset);        // Create and start five more numbered threads.        //        for(int i=0; i<=4; i++)
            {
                Thread t = new Thread(                new ParameterizedThreadStart(ThreadProc)
                );
                t.Start(i);
            }        // Wait until all the threads have started and blocked.        //        while (Interlocked.Read(ref threadCount) < 5)
            {
                Thread.Sleep(500);
            }        // Because the EventWaitHandle was created with        // ManualReset mode, signaling it releases all the        // waiting threads.        //        Console.WriteLine("Press ENTER to release the waiting threads.");
            Console.ReadLine();
            ewh.Set();
    
        }    public static void ThreadProc(object data)
        {        int index = (int) data;
    
            Console.WriteLine("Thread {0} blocks.", data);        // Increment the count of blocked threads.
            Interlocked.Increment(ref threadCount);        // Wait on the EventWaitHandle.        ewh.WaitOne();
    
            Console.WriteLine("Thread {0} exits.", data);        // Decrement the count of blocked threads.
            Interlocked.Decrement(ref threadCount);        // After signaling ewh, the main thread blocks on        // clearCount until the signaled thread has 
            // decremented the count. Signal it now.        //        clearCount.Set();
        }
    }
    登入後複製


     

    以上是.NET 同步與非同步 之 EventWaitHandle的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    本網站聲明
    本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

    熱AI工具

    Undresser.AI Undress

    Undresser.AI Undress

    人工智慧驅動的應用程序,用於創建逼真的裸體照片

    AI Clothes Remover

    AI Clothes Remover

    用於從照片中去除衣服的線上人工智慧工具。

    Undress AI Tool

    Undress AI Tool

    免費脫衣圖片

    Clothoff.io

    Clothoff.io

    AI脫衣器

    Video Face Swap

    Video Face Swap

    使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

    熱門文章

    <🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌
    北端:融合系統,解釋
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌
    Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
    3 週前 By 尊渡假赌尊渡假赌尊渡假赌

    熱工具

    記事本++7.3.1

    記事本++7.3.1

    好用且免費的程式碼編輯器

    SublimeText3漢化版

    SublimeText3漢化版

    中文版,非常好用

    禪工作室 13.0.1

    禪工作室 13.0.1

    強大的PHP整合開發環境

    Dreamweaver CS6

    Dreamweaver CS6

    視覺化網頁開發工具

    SublimeText3 Mac版

    SublimeText3 Mac版

    神級程式碼編輯軟體(SublimeText3)

    熱門話題

    Java教學
    1665
    14
    CakePHP 教程
    1424
    52
    Laravel 教程
    1321
    25
    PHP教程
    1269
    29
    C# 教程
    1249
    24
    c#.net的持續相關性:查看當前用法 c#.net的持續相關性:查看當前用法 Apr 16, 2025 am 12:07 AM

    C#.NET依然重要,因為它提供了強大的工具和庫,支持多種應用開發。 1)C#結合.NET框架,使開發高效便捷。 2)C#的類型安全和垃圾回收機制增強了其優勢。 3).NET提供跨平台運行環境和豐富的API,提升了開發靈活性。

    從網絡到桌面:C#.NET的多功能性 從網絡到桌面:C#.NET的多功能性 Apr 15, 2025 am 12:07 AM

    C#.NETisversatileforbothwebanddesktopdevelopment.1)Forweb,useASP.NETfordynamicapplications.2)Fordesktop,employWindowsFormsorWPFforrichinterfaces.3)UseXamarinforcross-platformdevelopment,enablingcodesharingacrossWindows,macOS,Linux,andmobiledevices.

    C#作為多功能.NET語言:應用程序和示例 C#作為多功能.NET語言:應用程序和示例 Apr 26, 2025 am 12:26 AM

    C#在企業級應用、遊戲開發、移動應用和Web開發中均有廣泛應用。 1)在企業級應用中,C#常用於ASP.NETCore開發WebAPI。 2)在遊戲開發中,C#與Unity引擎結合,實現角色控制等功能。 3)C#支持多態性和異步編程,提高代碼靈活性和應用性能。

    c#.net適合您嗎?評估其適用性 c#.net適合您嗎?評估其適用性 Apr 13, 2025 am 12:03 AM

    c#.netissutableforenterprise-levelapplications withemofrosoftecosystemdueToItsStrongTyping,richlibraries,androbustperraries,androbustperformance.however,itmaynotbeidealfoross-platement forment forment forment forvepentment offependment dovelopment toveloperment toveloperment whenrawspeedsportor whenrawspeedseedpolitical politionalitable,

    .NET中的C#代碼:探索編程過程 .NET中的C#代碼:探索編程過程 Apr 12, 2025 am 12:02 AM

    C#在.NET中的編程過程包括以下步驟:1)編寫C#代碼,2)編譯為中間語言(IL),3)由.NET運行時(CLR)執行。 C#在.NET中的優勢在於其現代化語法、強大的類型系統和與.NET框架的緊密集成,適用於從桌面應用到Web服務的各種開發場景。

    C#.NET與未來:適應新技術 C#.NET與未來:適應新技術 Apr 14, 2025 am 12:06 AM

    C#和.NET通過不斷的更新和優化,適應了新興技術的需求。 1)C#9.0和.NET5引入了記錄類型和性能優化。 2).NETCore增強了雲原生和容器化支持。 3)ASP.NETCore與現代Web技術集成。 4)ML.NET支持機器學習和人工智能。 5)異步編程和最佳實踐提升了性能。

    將C#.NET應用程序部署到Azure/AWS:逐步指南 將C#.NET應用程序部署到Azure/AWS:逐步指南 Apr 23, 2025 am 12:06 AM

    如何將C#.NET應用部署到Azure或AWS?答案是使用AzureAppService和AWSElasticBeanstalk。 1.在Azure上,使用AzureAppService和AzurePipelines自動化部署。 2.在AWS上,使用AmazonElasticBeanstalk和AWSLambda實現部署和無服務器計算。

    C#和.NET運行時:它們如何一起工作 C#和.NET運行時:它們如何一起工作 Apr 19, 2025 am 12:04 AM

    C#和.NET運行時緊密合作,賦予開發者高效、強大且跨平台的開發能力。 1)C#是一種類型安全且面向對象的編程語言,旨在與.NET框架無縫集成。 2).NET運行時管理C#代碼的執行,提供垃圾回收、類型安全等服務,確保高效和跨平台運行。

    See all articles