2015-04-28 125 views
0

我有一個靜態類來處理程序像這樣的事件處理程序MS SQL數據庫交互:C#處理多個事件的事件

public static event EventHandler<SQLExceptionEventArgs> SQLExceptionCaught; 

然後我有一個函數來處理它:

private static void OnSQLExceptionCaught(SqlException e) 
{ 
    if (SQLExceptionCaught != null) 
    { 
     SQLExceptionCaught(SQLExceptionCaught.Target, new SQLExceptionEventArgs(e)); 
    } 
} 

我還有一個從Windows.Forms.Form繼承的自定義窗體,它爲該事件處理程序添加了一個委託:

DBHandler.SQLExceptionCaught += this.handleSQLException; 

(當表格關閉時它被刪除)

然後這個委託在每個表格中被重寫。

當只有一個窗體打開時,它可以正常工作,但我無法使其適用於多個窗體,因此它只會從實際觸發事件的窗體觸發委託。

請您指出我的正確方向嗎?它甚至有可能嗎?

我很樂意考慮任何其他解決方案,只要它保留此功能。

+0

這沒有任何意義。除非您使用每個查詢/命令傳遞表單,否則您無法通過單個全局數據庫處理程序來完成此操作。實際上,這正是發送'SQLExceptionCaught.Target'的點,而不是實際的*發送者*。如果每個查詢/命令都通過發送者(導致查詢執行的實際表單),那麼您可以將發送者與處理程序中的'this'進行比較,並知道它是否是「您的」異常。但是,你可能寧願要保留一個單獨的DB處理程序實例。 – Luaan

回答

4

這聽起來像你應該把你的靜態類變成一個非靜態類。然後,您將有一個事件事件,以及該類的兩個實例(每個表單一個)。此時,兩個事件處理程序將被適當分離。從根本上說,你目前分享不當。

順便說一下,由於SQLExceptionCaught的值在檢查之後但在下一行之前變爲空,所以您當前的代碼可能會拋出NullReferenceException。通常你會解決這個問題用一個局部變量:

private static void OnSQLExceptionCaught(SqlException e) 
{ 
    var handler = SQLExceptionCaught; 
    if (handler != null) 
    { 
     handler(SQLExceptionCaught.Target, new SQLExceptionEventArgs(e)); 
    } 
} 

周圍有擴展方法和C#6中引入空條件運算符其他選項...看到my blog post on the topic瞭解更多詳情。

0

你可以找到問題的folows:

  • 打開多種形式。
  • 在您的OnSQLExceptionCaught中設置斷點。
  • 此時,使用方法GetInvocationList檢查事件SQLExceptionCaught的內容。如果它只有一個表單作爲訂戶,請檢查訂閱您的事件的代碼。
  • 它有多個訂戶,並且只有一個訂戶被調用,請確保訂戶不會拋出異常。如果在調用事件期間引發異常,則其他訂閱者不會被調用。