考虑以下代码:
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 方法。
假设 SendAsync 在 Foo 实例设置为 null 后完成,事件处理程序会发生什么?还火吗?如果我不想让它触发,我该如何正确清理 Foo 类,知道方法级别变量会产生事件。
最佳答案
是的,它仍然会开火。将变量设置为 null 不会触发垃圾回收或类似的操作。它只是将变量设置为 null。 (区分变量和实例很重要。不存在“将实例设置为 null”这样的概念。如果我将家庭住址写在一张纸上,然后再次擦掉,这不会破坏我的房子。)
听起来您可能希望您的 Dispose
方法“记住”该对象已被清理,然后如果在处置后调用 OnSendCompleted
,则忽略它。或者,跟踪所有“正在处理的请求”并在“Dispose”中取消它们...注意,在您取消全部请求时,某些请求可能会完成。/p>
还有一点需要注意:您几乎应该始终使用 using
语句,而不是显式调用 Dispose()
,这将确保 Dispose()
被调用,但 using
语句结束(例如出现异常)。
关于c# - 方法作用域变量的事件会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3724426/