2011-07-11 68 views
2

我有一个类可以触发事件委托给编组为DispatcherObject的目标,但是我遇到问题,如果处理程序在它的事件代码中引发异常,我应该怎么做?我不想阻止其他听众处理该事件。我正在寻找如何处理这样的问题的建议。关于处理多线程事件中的异常的建议

给出一个抽象基类与Saved事件,我的模式是如下:

public event EventHandler<EventArgs> Saved; 
public void Save() { 
    try { 
     OnSave(); 
    } catch (Exception) { 
     // What should I do here? throwing prevents subsequent handlers, 
     // while catching gobbles up the exception. Should this be in OnSave()? 
    } 
} 
protected virtual void OnSave() { 
    EventHandler<EventArgs> evt = Saved; 
    if (evt != null) { 
     var args = EventArgs.Empty; 
     foreach (var handler in evt.GetInvocationList()) { 
      var target = handler.Target as DispatcherObject; 
      if (target == null || target.CheckAccess()) { 
       var h = handler as EventHandler<EventArgs>; 
       if (h != null) h(this, args); 
      } else { 
       target.Dispatcher.Invoke(handler, this, args); 
      } 
     } 
    } 
} 

我想过建设一个拥有像ArrayException什么的所有异常的异常,但是这并未” t看起来没错。

建议在这里做什么将非常感激。

更新:我感谢丹尼尔和亨里克你的答案,如果我可以将两者都标记为答案,我会决定处理这个事件,因为我真的不希望它完全被忽视,我的最终解决方案如下(用于寻找解决方案的其他人)。

public event EventHandler<EventArgs> Saved; 
public void Save() { 
    OnSave(); 
} 
protected virtual void OnSave() { 
    EventHandler<EventArgs> evt = Saved; 
    if (evt != null) { 
     var args = EventArgs.Empty; 
     var handlers = evt.GetInvocationList(); 
     var exceptions = new Queue<Exception>(handlers.Length); 
     foreach (var handler in handlers) { 
      try { 
       var target = handler.Target as DispatcherObject; 
       if (target == null || target.CheckAccess()) { 
        var h = handler as EventHandler<EventArgs>; 
        if (h != null) h(this, args); 
       } else { 
        target.Dispatcher.Invoke(handler, this, args); 
       } 
      } catch (Exception ex) { 
       exceptions.Enqueue(ex); 
      } 
     } 
     if (exceptions.Count == 1) { 
      var ex = exceptions.Peek(); 
      throw new Exception(ex.Message, ex); 
     } 
     if (exceptions.Count > 0) { 
      throw new AggregateException(exceptions); 
     } 
    } 
} 

回答

2

无需创建您自己的ArrayException。您可以使用System.AggregateException来包装多个例外。

+0

现在,这是辉煌的,谢谢你。我发现这在.NET 4中是新的。我想我可能会喜欢在我的“On”方法中使用它。 –

1

从你的代码中,你似乎应该将循环中的调用包装到try/catch中,并且在那里吞噬异常。

我不明白OnSave调用者如何从所有事件处理函数中获得单一异常都能从中受益。既然你有多个事件句柄,并且从你的架构图来看,似乎每个人都做了一些完全不同的事情(因为每个事件都必须被调用),异常空间非常不同,因此调用者无论如何都无法处理它。

所以问题可能是:我如何处理更高级别上的多个事件异常?

您可以尝试纠正并重新运行OnSave?您是否必须省略通话成功?等等...

+0

Thankyou丹尼尔,你是对的,这个异常应该至少在事件内部被吞噬掉,尽管通过'Application.DispatcherUnhandledException'报告异常是很好的,而不是让它被注意到,这就是为什么我也许一个'ArrayException'可以保存可能发生的所有异常,这样他们就会拥有该网站的每个异常都来自甚至仅用于报告目的。 –

+0

吃个例外,在某处登录,然后从那里去... –