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

C# 在Silverlight中调用方法后,是否有理由从事件中删除该方法?,c#,silverlight,events,C#,Silverlight,Events,最近,我遇到越来越多的人,他们的代码与以下类似: 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

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

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,但仍然这样做似乎很愚蠢。 在对象的生命周期内,使用此方法而不只是在构造函数中装配回调有什么具体原因吗


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

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

i、 e.如果我们有:

publisher.SomeEvent += target.SomeHandler;
然后“publisher”将使“target”保持活动状态,但“target”将不保持活动状态 “出版商”活着

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


注意:如果只使用构造函数的方法结果是泄漏对象,我想您可以在
Dispose()
中取消订阅,但我不能说我见过这样的情况。

听起来您有两个问题:

  • 您正在尝试重用一个实际上只应使用一次的对象
  • 那个物体需要彻底清理
  • 您应该只使用SynchronousReader对象的一个实例一次(从而避免两个异步调用与其他地方提到的一个未能完成的调用相竞争),或者应该实现IDisposable以取消订阅事件并防止内存泄漏


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

    r.ReadCompleted+=this.ReadCompletedCallback在构造函数中?他不会订阅Read()中的事件,正常情况下,我还是会读的@HiTechMagic:在我看来,他通常订阅构造函数,从不退订。未注释掉的代码是他在其他人编写的代码中发现的。问题是,将其放入构造函数还是将其留在被调用的方法中是最佳做法,然后调用一个单独的异步方法,并在调用回调后将其删除。我刚才提到的一点是,如果按照这里实现的方式执行,那么两个异步调用竞相完成将失败,如果一个在另一个之前完成,那么回调将在刚刚完成的回调中被删除。注释掉的代码是我想要使用的实践,在我看来,实现后的代码是糟糕/混乱的东西。我的问题(在底部)表明包装器是不相关的。