方法作用域变量的事件会发生什么?

时间:2010-09-16 07:09:30

标签: c# visual-studio-2008 events dispose

请考虑以下代码:

public class Bar {
    Foo foo;
    void Go() {
       foo = new Foo();
       foo.Send(...);

       foo.Dispose();
       foo = null; 
    }
}

public class Foo : IDisposable {   
    public void Send(byte[] bytes) {
        SocketAsyncEventArgs args = new SocketAsyncEventArgs();
        args.SetBuffer(bytes, 0, bytes.Length);
        args.UserToken = socket;
        args.RemoteEndPoint = endPoint;
        args.Completed += new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);

        socket.SendAsync(args);
    }

    private void OnSendCompleted(object sender, SocketAsyncEventArgs e) {
        Debug.WriteLine("great");
    }

    public void Dispose() {
       //
    }
}

因此,类Bar运行Init方法,该方法实例化Foo类并触发Send方法,然后销毁Foo实例。 Send方法同时实例化一个方法级别SocketAsyncEventArgs,设置一个Completed事件,然后触发SendAsync方法。

假设在Foo实例设置为null后SendAsync完成,事件处理程序会发生什么?它还在开火吗?如果我不想激发它,我如何正确地清理Foo类,知道方法级变量产生了一个事件。

2 个答案:

答案 0 :(得分:3)

是的,它仍然会开火。将变量设置为null不会触发垃圾回收或类似的任何操作。它只是将变量设置为null。 (区分变量和实例很重要。没有“将实例设置为空”这样的概念。如果我将我的家庭地址写在一张纸上,然后再将它擦掉,这不会破坏我的房子。)

听起来您可能希望Dispose方法“记住”对象已被清理,然后如果在处理后调用OnSendCompleted,则忽略它。或者,跟踪任何“飞行中的请求”并在Dispose中取消它们...注意某些请求可能在完成时取消整个批次。

需要注意的另一点是:您应该几乎总是使用Dispose()语句,而不是显式调用using语句,这样可以确保调用Dispose() using {{1}}声明结束(例如,有例外)。

答案 1 :(得分:1)

尝试在OnSendCompleted方法中使用 - = 取消挂钩活动怎么样?

e.Completed -= new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);