请考虑以下代码:
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类,知道方法级变量产生了一个事件。
答案 0 :(得分:3)
是的,它仍然会开火。将变量设置为null不会触发垃圾回收或类似的任何操作。它只是将变量设置为null。 (区分变量和实例很重要。没有“将实例设置为空”这样的概念。如果我将我的家庭地址写在一张纸上,然后再将它擦掉,这不会破坏我的房子。)
听起来您可能希望Dispose
方法“记住”对象已被清理,然后如果在处理后调用OnSendCompleted
,则忽略它。或者,跟踪任何“飞行中的请求”并在Dispose
中取消它们...注意某些请求可能在完成时取消整个批次。
需要注意的另一点是:您应该几乎总是使用Dispose()
语句,而不是显式调用using
语句,这样可以确保调用Dispose()
using
{{1}}声明结束(例如,有例外)。
答案 1 :(得分:1)
尝试在OnSendCompleted方法中使用 - = 取消挂钩活动怎么样?
e.Completed -= new EventHandler<SocketAsyncEventArgs>(OnSendCompleted);