事件发件人获取在客户端的事件处理程序代码中处置

时间:2009-10-16 11:57:08

标签: c# events dispose handler

我面临以下情况(C#/ .Net在这里,但我认为这是一个普遍的问题):

  • 我们的一些对象类型(它们是集合)是一次性类型(C#中的IDisposable,允许客户明确告诉对象'不再需要你,释放所有资源')
  • 这些集合会触发事件('哦,我看,有人刚添加/删除/更改了元素')。
  • 在运行集合的客户端事件处理程序代码期间,此代码决定处理刚刚发送事件的对象(在语义上,这是一个正确的操作;例如:现在集合中不包含任何感兴趣的对象对我来说,所以我会摆脱它。)

这当然会对发送对象造成严重破坏。

目前的“解决方案”是在事件发生时保护(即禁止)处置:

private bool m_AllowDisposal;

private void MeFiringEvents()
{
    m_AllowDisposal = false;

    // Fire event
    if (m_MyEventHandlers != null)
    {
        m_MyEventHandlers(...);
    }

    m_AllowDisposal = true;
}

public void IDisposable.Dispose()
{
    if (m_AllowDisposal)
    {
        // Dispose resources, set members to null, etc
    }
}

private bool m_AllowDisposal; private void MeFiringEvents() { m_AllowDisposal = false; // Fire event if (m_MyEventHandlers != null) { m_MyEventHandlers(...); } m_AllowDisposal = true; } public void IDisposable.Dispose() { if (m_AllowDisposal) { // Dispose resources, set members to null, etc } }

正如您所看到的,这不是真正的解决方案,因为在客户端的事件处理代码中有效地禁止了对事件发送者的处理。

我能提出的任何其他解决方案都是

  • 每次触发事件后,检查客户端事件处理程序代码中是否发生了处理(或对对象的任何其他“错误”修改)。
  • 以防御方式退出发件人的代码(可以深入嵌套,直到发生事件为止)。

有趣的是,我没有在网上找到关于该主题的任何有用信息,尽管它看起来像是一般的showstopper。

也许你有个主意。

感谢您的考虑,

基督教

2 个答案:

答案 0 :(得分:1)

在我看来,为了保持适当的跟踪,同时发生了很多事情。

我会尝试将“处置对象”问题分开,例如在某种队列/处理管理器中添加待处理项目,这样可以处理(调用Dispose on)项目更安全,设计更好/理解和确定的方式。如果有的话,这应该有助于调试问题。

答案 1 :(得分:0)

如果您只需要一个应该处理对象的侦听器,可能会考虑一种不同的方法,可能是一个简单的回调(在.NET中实现Begin / End模式)。

处理事件的发送者在语义上并不合适:创建集合(或启动其创建)的对象应该负责处理它,而不是任意观察者。