3

我面临以下情况(这里是 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
    }
}

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

我能想出的任何其他解决方案都是这样的

  • 每次触发事件后,检查客户端的事件处理程序代码中是否发生了处置(或对对象的任何其他“不良”修改)。
  • 以一种防御性的方式摆脱发送者的代码(它可以被深度嵌套,直到它到达事件触发)。

有趣的是,我在网上没有找到关于该主题的任何有用信息,尽管它似乎是一个一般的展示者。

也许你有一个想法。

感谢您的考虑,

基督教

4

2 回答 2

1

在我看来,有很多事情同时发生以保持正确的跟踪。

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

于 2009-10-19T23:18:00.353 回答
0

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

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

于 2009-10-19T23:34:14.813 回答