2015-04-28 129 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的内容。如果它只有一个表单作为订户,请检查订阅您的事件的代码。
  • 它有多个订户,并且只有一个订户被调用,请确保订户不会抛出异常。如果在调用事件期间引发异常,则其他订阅者不会被调用。