真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

.NET同步與異步之EventWaitHandle的示例分析

這篇文章給大家分享的是有關(guān).NET同步與異步之EventWaitHandle的示例分析的內(nèi)容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。

西林網(wǎng)站制作公司哪家好,找成都創(chuàng)新互聯(lián)!從網(wǎng)頁設(shè)計、網(wǎng)站建設(shè)、微信開發(fā)、APP開發(fā)、成都響應(yīng)式網(wǎng)站建設(shè)公司等網(wǎng)站項目制作,到程序開發(fā),運營維護。成都創(chuàng)新互聯(lián)2013年至今到現(xiàn)在10年的時間,我們擁有了豐富的建站經(jīng)驗和運維經(jīng)驗,來保證我們的工作的順利進行。專注于網(wǎng)站建設(shè)就選成都創(chuàng)新互聯(lián)

WaitHandle提供了若干用于同步的方法。之前關(guān)于Mutex的blog中已經(jīng)講到一個WaitOne(),這是一個實例方法。除此之外,WaitHandle另有3個用于同步的靜態(tài)方法:

  • SignalAndWait(WaitHandle, WaitHandle):以原子操作的形式,向第一個WaitHandle發(fā)出信號并等待第二個。即喚醒阻塞在第一個WaitHandle上的線程/進程,然后自己等待第二個WaitHandle,且這兩個動作是原子性的。跟WaitOne()一樣,這個方法另有兩個重載方法,分別用Int32或者TimeSpan來定義等待超時時間,以及是否從上下文的同步域中退出。

  • WaitAll(WaitHandle[]):這是用于等待WaitHandle數(shù)組里的所有成員。如果一項工作,需要等待前面所有人完成才能繼續(xù),那么這個方法就是一個很好的選擇。仍然有兩個用于控制等待超時的重載方法,請自行參閱。

  • WaitAny(WaitHandle[]):與WaitAll()不同,WaitAny只要等到數(shù)組中一個成員收到信號就會返回。如果一項工作,你只要等最快做完的那個完成就可以開始,那么WaitAny()就是你所需要的。它同樣有兩個用于控制等待超時的重載。

線程相關(guān)性

  • Mutex與Monitor一樣,是具有線程相關(guān)性的。我們之前已經(jīng)提到過,只有通過Monitor.Enter()/TryEnter()獲得對象鎖的線程才能調(diào)用Pulse()/Wait()/Exit();同樣的,只有獲得Mutex擁有權(quán)的線程才能執(zhí)行ReleaseMutex()方法,否則就會引發(fā)異常。這就是所謂的線程相關(guān)性。

  • 相反,EventWaitHandle以及它的派生類AutoResetEvent和ManualResetEvent都是線程無關(guān)的。任何線程都可以發(fā)信號給EventWaitHandle,以喚醒阻塞在上面的線程。

Event通知

EventWaitHandle、AutoResetEvent、ManualResetEvent名字里都有一個“Event”,不過這跟.net的本身的事件機制完全沒有關(guān)系,它不涉及任何委托或事件處理程序。相對于我們之前碰到的Monitor和Mutex需要線程去爭奪“鎖”而言,我們可以把它們理解為一些需要線程等待的“事件”。線程通過等待這些事件的“發(fā)生”,把自己阻塞起來。一旦“事件”完成,被阻塞的線程在收到信號后就可以繼續(xù)工作。

為了配合WaitHandle上的3個靜態(tài)方法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:將事件狀態(tài)設(shè)置為終止狀態(tài),允許一個或多個等待線程繼續(xù)。初看“signaled”和“終止”似乎并不對應(yīng),細想起來這兩者的說法其實也不矛盾。事件如果在進行中,當然就沒有“終止”,那么其它線程就需要等待;一旦事件完成,那么事件就“終止”了,于是我們發(fā)送信號喚醒等待的線程,所以“信號已發(fā)送”狀態(tài)也是合理的。兩個小細節(jié):

      1. 無論中文還是英文版,都提到這個方法都是可以讓“一個”或“多個”等待線程“繼續(xù)/Proceed”(注意不是“喚醒”)。所以這個方法在“喚醒”這個動作上是類似于Monitor.Pulse()和Monitor.PulseAll()的。至于什么時候類似Pulse(),又在什么時候類似PulseAll(),往下看。

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

    • bool:Reset():Sets the state of the event to nonsignaled, causing threads to block. 將事件狀態(tài)設(shè)置為非終止狀態(tài),導(dǎo)致線程阻止。 同樣,我們需要明白“nonsignaled”和“非終止”是一回事情。還同樣的是,仍然有個無厘頭的返回值。Reset()的作用,相當于讓事件重新開始處于“進行中”,那么此后所有WaitOne()/WaitAll()/WaitAny()/SignalAndWait()這個事件的線程都會再次被擋在門外。

構(gòu)造函數(shù)

來看看EventWaitHandle眾多構(gòu)造函數(shù)中最簡單的一個:

  • EventWaitHandle(Boolean initialState, EventResetMode mode):初始化EventWaitHandle類的新實例,并指定等待句柄最初是否處于終止狀態(tài),以及它是自動重置還是手動重置。大多數(shù)時候我們會在第一個參數(shù)里使用false,這樣新實例會缺省為“非終止”狀態(tài)。第二個參數(shù)EventResetMode是一個枚舉,一共兩個值:

    1. EventResetMode.AutoReset:當Set()被調(diào)用當前EventWaitHandle轉(zhuǎn)入終止狀態(tài)時,若有線程阻塞在當前EventWaitHandle上,那么在釋放一個線程后EventWaitHandle就會自動重置(相當于自動調(diào)用Reset())再次轉(zhuǎn)入非終止狀態(tài),剩余的原來阻塞的線程(如果有的話)還會繼續(xù)阻塞。如果調(diào)用Set()后本沒有線程阻塞,那么EventWaitHandle將保持“終止”狀態(tài)直到一個線程嘗試等待該事件,這個該線程不會被阻塞,此后EventWaitHandle才會自動重置并阻塞那之后的所有線程。

    2. EventResetMode.ManualReset:當終止時,EventWaitHandle 釋放所有等待的線程,并在手動重置前,即Reset()被調(diào)用前,一直保持終止狀態(tài)。

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

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

    1. Set()的作用不僅僅是“喚醒”而是“釋放”,可以讓線程繼續(xù)工作(proceed);相反,Pulse()喚醒的線程只是重新進入Running狀態(tài),參與對象鎖的爭奪,誰都不能保證它一定會獲得對象鎖。

    2. Pulse()的已被調(diào)用的狀態(tài)不會被維護。因此,如果在沒有等待線程時調(diào)用Pulse(),那么下一個調(diào)用Monitor.Wait()的線程仍然會被阻塞,就像Pulse() 沒有被被調(diào)用過。也就是說Monitor.Pulse()只在調(diào)用當時發(fā)揮作用,并不象Set()的作用會持續(xù)到下一個WaitXXX()。

  • 在一個工作在ManualReset模式下的EventWaitHandle的Set()方法被調(diào)用時,它所起到的喚醒作用與Monitor.PulseAll()類似,所有被阻塞的線程都會收到信號被喚醒。而兩者的差別與上面完全相同。

來看看EventWaitHandle的其它構(gòu)造函數(shù):

  • EventWaitHandle(Boolean initialState, EventResetMode mode, String name):頭兩個參數(shù)我們已經(jīng)看過,第三個參數(shù)name用于在系統(tǒng)范圍內(nèi)指定同步事件的名稱。是的,正如我們在Mutex一篇中提到的,由于父類WaitHandle是具有跨進程域的能力的,因此跟Mutex一樣,我們可以創(chuàng)建一個全局的EventWaitHandle,讓后將它用于進程間的通知。注意,name仍然是大小寫敏感的,仍然有命名前綴的問題跟,你可以參照這里。當name為null或空字符串時,這等效于創(chuàng)建一個局部的未命名的EventWaitHandle。仍然同樣的還有,可能會因為已經(jīng)系統(tǒng)中已經(jīng)有同名的EventWaitHandle而僅僅返回一個實例表示同名的EventWaitHandle。所以最后仍舊同樣地,如果你需要知道這個EventWaitHandle是否由你最先創(chuàng)建,你需要使用以下兩個構(gòu)造函數(shù)之一。

  • EventWaitHandle(Boolean initialState, EventResetMode mode, String name, out Boolean createdNew):createdNew用于表明是否成功創(chuàng)建了EventWaitHandle,true表明成功,false表明已經(jīng)存在同名的事件。

  • EventWaitHandle(Boolean initialState, EventResetMode mode, String name, out Boolean createdNew, EventWaitHandleSecurity):關(guān)于安全的問題,直接查看這個構(gòu)造函數(shù)上的例子吧。全局MutexEventWaitHandle的安全問題應(yīng)該相對Mutex更需要注意,因為有可能黑客程序用相同的事件名對你的線程發(fā)送信號或者進行組織,那樣可能會嚴重危害你的業(yè)務(wù)邏輯。

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

感謝各位的閱讀!關(guān)于“.NET同步與異步之EventWaitHandle的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!


當前標題:.NET同步與異步之EventWaitHandle的示例分析
轉(zhuǎn)載來于:http://weahome.cn/article/jjephj.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部