簡體   English   中英

注冊c#事件是否安全?

[英]is it thread safe to register for a c# event?

具體來說,是“+ =”操作原子? 如果我使用'event'關鍵字,或只是一個普通的老代表,它會有所作為嗎?

對於大多數類型,它是一個讀取,然后是“+”運算符,然后是一個寫入。 所以,它不是原子的。 我想知道代表/活動是否有特殊情況。

這種代碼是必要的還是冗余的:

Action handler;
object lockObj;
public event Action Handler {
    add { lock(lockObj) { handler += value; } }
    remove { lock(lockObj) { handler -= value; } }
}

是的, 自動實現的事件上的+=-=運算符是原子的(如果庫使用自定義事件處理程序,它很容易不是原子的)。 來自MSDN雜志文章.NET Matters:Event Accessors

當C#編譯器為MyClass生成代碼時,輸​​出Microsoft®中間語言(MSIL)的行為與使用圖1中的代碼生成的相同。

圖1擴展事件實現

 class MyClass { private EventHandler _myEvent; public event EventHandler MyEvent { [MethodImpl(MethodImplOptions.Synchronized)] add { _myEvent = (EventHandler)Delegate.Combine(_myEvent, value); } [MethodImpl(MethodImplOptions.Synchronized)] remove { _myEvent = (EventHandler)Delegate.Remove(_myEvent, value); } } ... } 

[...]

顯式事件實現的另一個用途是提供自定義同步機制(或刪除一個)。 您將在圖1中注意到,添加和刪除訪問器都使用MethodImplAttribute進行裝飾,該MethodImplAttribute指定應同步訪問者。 對於實例事件,此屬性等效於使用當前實例上的鎖來包裝每個訪問者的內容:

 add { lock(this) _myEvent += value; } remove { lock(this) _myEvent -= value; } 

如前所述這里add處理程序是自動實現的,將執行比鎖更好線程安全的方式。

在涉及事件的線程安全時,您需要更加小心的是如何調用它們。 見埃里克利珀的對這個職位在這里

觸發此事件的標准模式是:

 Action temp = Foo; if (temp != null) temp(); 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM