2011-08-11 233 views
7

,我有以下事件處理程序的調用:的事件處理程序

private EventHandler<MyEventArgs> _myEventHandler; 
public event EventHandler<MyEventArgs> MyEvent 
{ 
    add { _myEventHandler += value; } 
    remove { _myEventHandler -= value; } 
} 

有人能解釋一下下面的代碼片段之間的區別?
片段事件處理(A):

//Snippet A: 
if (_myEventHandler != null) 
{ 
    _myEventHandler(new MyEventArgs()); 
} 

片段的BeginInvoke(B):

//Snippet B: 
if (_myEventHandler != null) 
{ 
    _myEventHandler.BeginInvoke(new MyEventArgs(), ar => 
    { 
    var del = (EventHandler<MyEventArgs>)ar.AsyncState; 
    del.EndInvoke(ar); 
    }, _myEventHandler); 
} 

對於澄清:什麼是調用的事件處理程序 「只是因爲它是」,用BeginInvoke之間的區別?

回答

12

BeginInvoke方法是異步的,這意味着它是在不同的線程上引發的。如果人們不期望這會很危險,而且對事件來說很少見 - 但它可能很有用。

另外,還要注意嚴格地說你應該快照事件句柄值 - 這是尤其 true,如果(通過Begin*)你正在處理的線程。

var tmp = _myEventHandler; 
if(tmp != null) { 
    tmp(sender, args); 
} 

而且 - 注意,你的事件訂閱本身不是線程安全的;再次,這只是事情,如果你正在處理多線程,但內置的現場般的事件線程安全:

public event EventHandler<MyEventArgs> MyEvent; // <===== done; nothing more 

這裏迴避的問題是:

  • 與快照,我們避免了最後一位用戶在空檢查和調用之間取消訂閱的風險(這意味着他們可能會得到他們並不期望的事件,但這意味着我們不會殺死引發的線程)
  • 與類似現場的事件變化,我們避免了失去訂閱/取消訂閱的風險當兩個線程在同一時間做這個
+1

它不一定叫在不同的線程是嗎?異步調用委託仍然在同一個線程上執行,但返回阻止AFAIK的時刻。 –

+1

@Jeff no;異步調用委託意味着它發生在工作線程上。它會如何不同步運行?請注意,這與Control.BeginInvoke略有不同,如果您已經在UI線程上,它可能會在同一線程上繼續 –

+0

如果正在調用的代理正在執行IO(即塊),則控制權會返回到呼叫站點。完成後,原始線程將被中斷以完成該方法的其餘部分。據我瞭解,沒有創建新線程,它是從那裏的所有中斷。 –

5

BeginInvoke()呼叫immediatelly控制返回給調用線程,並運行在從ThreadPool一個單獨的線程的委託,所以這將是某種形式的異步執行的。