2011-05-08 60 views
1

目標:我想多次訂閱不同類別中的相同活動。我有下面的類:使用EventHandlerList多次訂閱活動

public class MyEngine : IEngine 
{ 
    private EventHandlerList _events = new EventHandlerList(); 

    protected EventHandlerList Events 
    { 
     get 
     { 
      return _events; 
     } 
    } 

    private readonly string OnReceivedEventName = "OnReceived"; 

    public event MessageEventHandler OnReceived 
    { 
     add 
     { 
      lock (this) 
      { 
       Events.AddHandler(OnReceivedEventName, value); 
      } 
     } 
     remove 
     { 
      lock (this) 
      { 
       Events.RemoveHandler(OnReceivedEventName, value); 
      } 
     } 
    } 

    protected internal virtual void MessageReceived(MessageEventArgs e) 
    { 

     var handler = Events[OnReceivedEventName] as MessageEventHandler; 
     TryFireMessageEvent(handler, e); 
    } 

    private void TryFireMessageEvent(MessageEventHandler handler, MessageEventArgs e) 
    { 
     try 
     { 
      if (handler != null) 
       handler.Invoke(this, e); 
     } 
     catch (Exception ex) 
     { 
      log.Error("Message Received - Exception caught", ex); 
      ErrorOccurred(ex); 
     } 
    } 
} 

主要模塊有IEngine的一個實例:

public class MyProvider 
{ 
    protected internal IEngine Engine { get; set; } 
    public MyProvider(IEngine engine) 
    { 
     Engine = engine; 
     engine.OnReceived += Engine_Received; 
    } 
    protected internal void Engine_Received(IEngine engine, MessageEventArgs args) 
    {...} 
} 

我也有一個功能「DoAction」,創造一個操作並注入發動機:

public class MyProvider 
{ 
    .... 
    public Result DoAction() 
    { 
     using (var operation = new SyncOperation(Engine)) 
     { 
      operationResult = operation.Execute(); 
     } 
    } 
} 

的SyncOperation:

public class SyncOperation : IDisposable 
{ 
    private IEngine _engine; 

    public SyncOperation (IEngine engine) 
    { 
     Ensure.NotNull(engine, "engine"); 
     _engine = engine; 

     _engine.OnReceived += Engine_OnReceived; 
    } 

    internal void Engine_OnReceived(IEngine engine, MessageEventArgs args) 
    {...} 
} 

當調用operation.Execute();並非所有收到的事件都在SyncOperation類中引發。

我錯過了什麼嗎?

+0

相當有點coce,我仍然不確定我們有一個概述...也許發佈TryFireMessageEvent呢? – 2011-05-08 21:13:56

回答

0

我比較你的代碼和一個已知的好例子,我對private readonly string OnReceivedEventName作爲對象鍵有懷疑。你在這裏依賴字符串實習,'普通'是一個靜態對象。

這讓我想知道正常生成的事件是否是線程安全的。找不到參考的那麼快,但作爲一個診斷:

public event MessageEventHandler OnReceived; 

威力有競爭條件的話,但是這將是非常罕見的(且易於最小化/消除)。所有的處理程序都會被調用嗎?

+0

我不認爲所有的處理程序都會被調用。有時SyncOperation處理程序被調用,有時MyProvider處理程序被調用 – 2011-05-08 21:36:56

+0

@Anibas:我的意思是用';'來代替。 – 2011-05-08 21:41:51

+0

謝謝!你能否更詳細地解釋問題是什麼? – 2011-05-08 21:50:10