none
AutoResetEvent,ManualResetEvent RRS feed

  • 問題

  • 目前使用執行緒,看msdn上的解說,
    還是不太了解這2個的分別,使用上也是照著做。
    想問各位,可以給我簡單詳細的解說或參考
    2009年3月10日 上午 07:00

解答

  • 不是啦..
    是AutoReset會自己回復為等待狀態
    而ManualRest一定要另外下 Reset才會回復為等待狀態
    我仔細解釋第二個程序
    j=0
    進入子執行緒
    Messagebox跳出來
    i=i+1
    所以i變成1
    遇到WaitOne,所以主執行緒停住,
    直到myResetEvent set(),解除鎖定訊號
    j=1
    進入子執行緒
    MessageBox跳出來
    i=i+1
    遇到WaitOne,因為ManualResetEvent沒有Reset,所以他就不停繼續J=2的迴圈......一直到迴圈結束
    所以你有可能會跳出五個Messagebox裡面的值都沒改變
    原因是當j=1時,它搞不好還來不及變化 i 的值,j=2的子執行緒就啟動了
    ===============================================
    當第三個範例加上 myResetEvent.Reset之後,其實他所執行的結果是和範例一相同的
    ===============================================
    用白話文應該這樣講
    當使用AutoResetEvent時,如果一開始就設定遇到WaitOne要停止,他在啟動子執行緒之後遇到WaitOne就會停住,然後子執行緒執行完畢後Set ResetEvent的訊號告訴主執行緒可以繼續下一個步驟,而在此同時ResetEvent也會記得下一次碰到WaitOne還是要停住

    當使用ManualResetEvent時,如果一開始就設定遇到WaitOne要停止,他在啟動子執行緒之後遇到WaitOne就會停住,後子執行緒執行完畢後Set ResetEvent的訊號告訴主執行緒可以繼續下一個步驟,如果不手動去作ManaulResetEvent.Reset()的話,主執行緒下次遇到WaitOne()就不會等待,因為訊號並沒被Reset成"未接收信號"狀態
    =======================================================================
    通常比較單純的狀況就是每次遇到WaitOne就要停,那就用AutoResetEvent,如果遇到WaitOne不一定要停(因為可能會依據其它執行緒的結果來決定要不要停),就用ManualResetEvent
    不過小弟習慣用ManualResetEvent啦,因為反正記得Reset就好



    • 已標示為解答 ericstone 2009年3月10日 下午 02:27
    2009年3月10日 上午 10:02
    版主

所有回覆

  •  基本上就和它的名字一樣...一個會自動Reset,一個要手動才能Reset
    來個簡單的實驗
    1.AutoReset
     Dim i As Integer = 0 
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click  
            Dim myResetEvent As New AutoResetEvent(False)  
            Dim j As Integer  
            For j = 0 To 5  
                ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Test), myResetEvent)  
                myResetEvent.WaitOne()  
            Next  
        End Sub  
        Private Sub Test(ByVal state As Object)  
            MessageBox.Show(i)  
            i = i + 1  
            CType(state, AutoResetEvent).Set()  
     
        End Sub 
    執行這個,你會發現,Messagebox每次跑出來以後,你一定要按確定才會出現下一個,因為在Set之後回到Waitone的下一個步驟myResetEvent就自動Reset了

    2.ManualResetEvent
    Dim i As Integer = 0 
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click  
            Dim myResetEvent As New ManualResetEvent(False)  
            Dim j As Integer  
            For j = 0 To 5  
                ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Test), myResetEvent)  
                myResetEvent.WaitOne()  
            Next  
        End Sub  
        Private Sub Test(ByVal state As Object)  
            MessageBox.Show(i)  
            i = i + 1  
            CType(state, ManualResetEvent).Set()  
        End Sub 
    執行這個,你會發現,Messagebox第一次跑出來(也就是出現0)的那一次,他會等待,當你按下"確定",稍微等一下,你就會看到一堆Messagebox跑出來,因為第一次主執行緒會在WaitOne等待,但當我們Set它之後,他遇到WaitOne就不會理了
    所以要用ManualResetEvent正確執行出(1)的結果,就必須手動去Reset myResetEvent
    也就是要改成以下形式,它才會在每次WaitOne的地方等待訊號
     Dim i As Integer = 0 
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click  
            Dim myResetEvent As New ManualResetEvent(False)  
            Dim j As Integer  
            For j = 0 To 5  
                ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf Test), myResetEvent)  
                myResetEvent.WaitOne()  
                '要多這一行  
                myResetEvent.Reset()  
            Next  
        End Sub  
        Private Sub Test(ByVal state As Object)  
            MessageBox.Show(i)  
            i = i + 1  
            CType(state, ManualResetEvent).Set()  
        End Sub 

    這個用VB.NET寫的..你可以參考改成C#
    2009年3月10日 上午 08:30
    版主
  • 所以autoreset 像是排隊一樣一個接一個拿東西
    manual一旦開始就是看誰跑得快去搶東西
    那應該針對什麼情況 來做這2個的分別?

    2009年3月10日 上午 09:38
  • 不是啦..
    是AutoReset會自己回復為等待狀態
    而ManualRest一定要另外下 Reset才會回復為等待狀態
    我仔細解釋第二個程序
    j=0
    進入子執行緒
    Messagebox跳出來
    i=i+1
    所以i變成1
    遇到WaitOne,所以主執行緒停住,
    直到myResetEvent set(),解除鎖定訊號
    j=1
    進入子執行緒
    MessageBox跳出來
    i=i+1
    遇到WaitOne,因為ManualResetEvent沒有Reset,所以他就不停繼續J=2的迴圈......一直到迴圈結束
    所以你有可能會跳出五個Messagebox裡面的值都沒改變
    原因是當j=1時,它搞不好還來不及變化 i 的值,j=2的子執行緒就啟動了
    ===============================================
    當第三個範例加上 myResetEvent.Reset之後,其實他所執行的結果是和範例一相同的
    ===============================================
    用白話文應該這樣講
    當使用AutoResetEvent時,如果一開始就設定遇到WaitOne要停止,他在啟動子執行緒之後遇到WaitOne就會停住,然後子執行緒執行完畢後Set ResetEvent的訊號告訴主執行緒可以繼續下一個步驟,而在此同時ResetEvent也會記得下一次碰到WaitOne還是要停住

    當使用ManualResetEvent時,如果一開始就設定遇到WaitOne要停止,他在啟動子執行緒之後遇到WaitOne就會停住,後子執行緒執行完畢後Set ResetEvent的訊號告訴主執行緒可以繼續下一個步驟,如果不手動去作ManaulResetEvent.Reset()的話,主執行緒下次遇到WaitOne()就不會等待,因為訊號並沒被Reset成"未接收信號"狀態
    =======================================================================
    通常比較單純的狀況就是每次遇到WaitOne就要停,那就用AutoResetEvent,如果遇到WaitOne不一定要停(因為可能會依據其它執行緒的結果來決定要不要停),就用ManualResetEvent
    不過小弟習慣用ManualResetEvent啦,因為反正記得Reset就好



    • 已標示為解答 ericstone 2009年3月10日 下午 02:27
    2009年3月10日 上午 10:02
    版主
  • 恩,我知道了,所以manualResetEvent 是可以依照 user來決定 是否要暫停
    所以manualResetEvent有比較大的使用彈性,可以針對 執行程式的重要性來執行囉?
    2009年3月10日 上午 10:30