2009-05-03 83 views
17

您會如何建議避免重複事件訂閱的最佳方式?如果這行代碼在兩個地方執行,則該事件將運行兩次。我試圖避免第三方事件訂閱兩次。避免C#中的重複事件訂閱

theOBject.TheEvent += RunMyCode; 

在我的委託制定者,我可以有效地運行這個...

theOBject.TheEvent -= RunMyCode; 
theOBject.TheEvent += RunMyCode; 

,但是,最好的辦法?

回答

19

我認爲,最有效的方法,就是讓你的事件屬性,並在此Example增加併發鎖把它作爲:

private EventHandler _theEvent; 
private object _eventLock = new object(); 
public event EventHandler TheEvent 
{ 
    add 
    { 
     lock (_eventLock) 
     { 
      _theEvent -= value; 
      _theEvent += value; 
     } 
    } 
    remove 
    { 
     lock (_eventLock) 
     { 
      _theEvent -= value; 
     } 
    } 
} 
+2

Dave Morton改變了他的域名。新的網址是:http://codinglight.blogspot.com/2009/02/preventing-duplicate-subscriptions-to.html – 2011-02-02 21:16:33

+0

僅供參考,如果您在鏈接中獲得503,則只需刷新頁面即可。它似乎加載了幾次嘗試後。 – Dan 2014-09-30 18:32:32

1

如果您擁有類theObject的來源,那麼您可以訪問TheEvent的InvocationList。您可以實現您自己的添加訪問器,並在添加之前進行檢查。

不過,我認爲你的做法是沒關係。

2

是你的代碼的多線程?只有多線程時才需要併發鎖定。如果不是它的開銷。

因此您的退訂和訂閱的做法是正確的。

謝謝

0

我使用你的方法,除了一個細節。我認爲,創建訂閱者或object的新實例時應該訂閱事件,這會使代碼更直觀。因此,所有你需要的只是在正確的對象配置後仔細觀看(配置方便的解決方案)。

你提到你使用第三方事件,這意味着你不能提供你自己的添加/刪除方法的實現,因爲你已經被建議。但是在你自己的事件中,你應該定義自己的事件添加/刪除方法,以解決你的問題。

4

之前,我已經這樣做了....它假定它是可以接受的,最後的用戶就是被調用。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyObject my = new MyObject(); 
      my.Changed += new EventHandler(my_Changed); 
      my.Changed += new EventHandler(my_Changed1); 

      my.Update(); 
      Console.ReadLine(); 
     } 

     static void my_Changed(object sender, EventArgs e) 
     { 
      Console.WriteLine("Hello"); 
     } 
     static void my_Changed1(object sender, EventArgs e) 
     { 
      Console.WriteLine("Hello1"); 
     } 
    } 
    public class MyObject 
    { 
     public MyObject() 
     { 
     } 
     private EventHandler ChangedEventHandler; 
     public event EventHandler Changed 
     { 
      add 
      { 
       ChangedEventHandler = value; 
      } 
      remove 
      { 
       ChangedEventHandler -= value; 
      } 
     } 
     public void Update() 
     { 
      OnChanged(); 
     } 

     private void OnChanged() 
     { 
      if (ChangedEventHandler != null) 
      { 
       ChangedEventHandler(this, null); 
      } 
     } 
    } 
}