我有一个类可以触发委托给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
之类的所有异常的异常,但这似乎不对。
非常感谢有关如何做的建议。
更新:我感谢Daniel和Henrik的回答,如果我能将两者都标记为答案,我决定去处理这个事件,因为我真的不想要它完全没有被注意到,我的最终解决方案如下(对于寻找解决方案的其他人)。
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);
}
}
}
答案 0 :(得分:2)
无需创建自己的ArrayException
。您可以使用System.AggregateException
包装多个例外。
答案 1 :(得分:1)
从您的代码中,您似乎应该将循环中的调用包装到try / catch中,并在那里插入异常。
我没有看到OnSave
调用者如何从所有事件处理程序中获得单个异常中受益。由于你有多个事件句柄,并且从你的架构草图看起来每个人都做了完全不同的事情(因为每个人都必须被调用),异常空间是如此异构,所以调用者无论如何都无法处理它。
所以问题可能是:我如何处理更高级别的多个事件异常?
您可以尝试更正并重新运行OnSave
吗?你必须省略成功的电话吗?等等...