在 Silverlight 中调用方法后,是否有理由从事件中删除该方法

本文关键字:方法 事件 删除 有理由 Silverlight 调用 是否 | 更新日期: 2023-09-27 18:36:26

最近我遇到了越来越多的人拥有类似于以下内容的代码:

private AsynchronousReader r;
public SynchronousReader()
{
    r = new AsynchronousReader();
    // My practice is to put this here
    // and then never remove it and never add it again
    // thus cleaning up the code and preventing constant add/remove.
    //r.ReadCompleted += this.ReadCompletedCallback;
}
private ReadCompletedCallback()
{
    // Remove the callback to "clean things up"...
    r.ReadCompleted -= this.ReadCompletedCallback;
    // Do other things
}
public Read()
{
    r.ReadCompleted += this.ReadCompletedCallback;
    // This call completes asynchronously and later invokes the above event
    r.ReadAsync();
    r.WaitForCompletion();
}

人们说这种做法比我上面指出的要好,并且给出了几个特定于 Silverlight 的原因。他们说它可以防止内存泄漏、线程问题,甚至这是正常的做法。

我没有做过太多的Silverlight,但这样做似乎还是很愚蠢的。是否有任何特定原因会使用此方法,而不仅仅是在构造函数中一次并在对象的生存期内绑定回调?

这就像我举个例子一样简单。忽略这样一个事实,即它是一种将异步对象转换为同步对象的包装器。我只是对添加和删除事件的方式感到好奇。

在 Silverlight 中调用方法后,是否有理由从事件中删除该方法

如果您提到,将其挂接一次是有意义的,但对象(父对象和/或子对象)可能不会被垃圾回收,因为事件处理程序仍然引用它们。

根据马克·加维尔在这里

即,如果我们有:

publisher.SomeEvent += target.SomeHandler;
那么"发布者"将使"目标"保持

活动状态,但"目标"不会保持 "出版商"活着。

要记住的更重要的一点可能是子对象的生存期。如果它与父级相同,则构造函数中的一次性订阅更有意义。如果它是动态的,您可能希望删除处理程序,因为我看到它们泄漏(导致多次回调)。

注意:如果仅构造函数方法泄漏了对象,您始终可以在我猜的Dispose()中取消订阅,但我不能说我曾经见过。

听起来您有两个问题:

  1. 您正在尝试重用实际上只应该使用一次的对象。
  2. 该对象需要正确清理。

实际上,您应该只使用 SyncReader 对象的实例一次(从而避免两个异步调用争用,其中一个无法完成,就像您在其他地方提到的那样),或者您应该实现 IDisposable 以取消订阅事件并防止内存泄漏。

第三种解决方案可能是可能的:保留 SynchronousReader 的单个实例,但每次调用 SynchronousReader.Read 都会创建一个新的 AsynchronousReader 实例(而不是将其存储为实例中的私有字段)。 然后,您可以保留上面大部分您不喜欢的代码,但可以正确处理事件订阅。