2010-02-05 116 views
13

我應該在以下情況下鎖定事件:我應該鎖定'事件'嗎?

event foo;

線程A:將調用foo + = handler;

線程B:將調用foo - = handler;

我應該鎖foo嗎?

+1

喬恩的回答很好,但在回答之前,我會推回去問爲什麼你首先要做鎖定。 *你相信你有什麼問題,你爲什麼認爲鎖定解決了它?*我可以想到多線程事件可能存在的多個問題;你會根據你擔心的問題使用不同的鎖定技術。 – 2010-02-05 18:24:54

回答

24

鎖定foo是個壞主意,因爲每次值都會改變。您應該鎖定在其變化的變量:

private readonly object eventLock = new object(); 
private EventHandler fooHandler; 

public event EventHandler Foo 
{ 
    add 
    { 
     lock (eventLock) 
     { 
      fooHandler += value; 
     } 
    } 
    remove 
    { 
     lock (eventLock) 
     { 
      fooHandler -= value; 
     } 
    } 
} 

private void OnFoo(EventArgs e) 
{ 
    EventHandler handler; 
    lock (eventLock) 
    { 
     handler = fooHandler; 
    } 
    if (handler != null) 
    { 
     handler(this, e); 
    } 
} 

需要注意的是,如果你使用類似字段的事件,像這樣:

public event EventHandler Foo; 

那麼你會自動獲得一個「在添加/刪除時鎖定(this)「,儘管您在調用處理程序之前必須手動添加它(假設您要確保讀取最近寫入的值)。就我個人而言,我不是鎖定「this」的粉絲,但你可能不介意 - 它確實使代碼更簡單。

+0

@Jon,我正在使用類似場景的事件,所以我不需要鎖定添加/刪除,我是對嗎? – Benny 2010-02-05 08:17:54

+0

@Jon,我直接調用了事件處理函數,像這樣foo(),不會從事件中獲取處理函數,我應該添加鎖嗎? – Benny 2010-02-05 08:24:42

+1

@Benny:如果你使用的是類似場景的事件,你不需要*添加/刪除來鎖定。如果你直接調用事件處理程序,你如何防止它爲空?請注意,您不能只使用'if(foo!= null){foo(...); }'as'foo'可以在測試後變成* null。也不能保證你會得到最新的值 - 這就是爲什麼我在我的'OnFoo'方法中獲得鎖定的原因。 (內存模型可以做些有趣的事情......) – 2010-02-05 08:26:40

相關問題