0

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

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,但仍然这样做似乎很愚蠢。是否有任何具体原因可以使用此方法,而不仅仅是在构造函数中安装回调一次并在对象的生命周期内?

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

4

2 回答 2

1

在您提到的情况下,其连接一次是有意义的,但由于事件处理程序仍引用它们,因此对象(父和/或子)可能不会被垃圾收集。

根据Marc Gavel 这里

即如果我们有:

publisher.SomeEvent += target.SomeHandler;

那么“发布者”将使“目标”保持活动状态,但“目标”不会让“发布者”保持活动状态。

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

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

于 2012-06-07T15:29:27.817 回答
-1

听起来你有两个问题:

  1. 您正在尝试重用一个真正应该只使用一次的对象。
  2. 该对象需要得到适当的清理。

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

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

于 2012-06-07T16:03:24.103 回答