只是想知道异步TCP或其他EAP模式,如果成功处理程序的引用为this
,例如理论上,this.state
存在对当前实例的引用,因为this
通过闭包性质保存在某个生成的对象范围中。因此,即使创建实例的范围已完成执行,实例本身也不应被垃圾收集?
我的代码类似于以下内容:
public class ATcpClient
{
private ATcpState state = null;
private void Receive()
{
// create the callback here, in order to use in dynamic
AsyncCallback ReceiveCallback = delegate(IAsyncResult ar)
{
try
{
// Read data from the remote device.
this.state.BytesReceived = this.state.Socket.EndReceive(ar);
}
catch (Exception e)
{
// ...
}
};
try
{
this.state.Socket.BeginReceive(this.state.Buffer, 0, this.state.BufferSize, 0,
ReceiveCallback, null);
}
catch (Exception e)
{
// ...
// ...
}
}
}
执行它的代码可能如下所示:
public void DoExecuteCode()
{
new ATcpClient().Receive();
}
实例是GC会导致Receive()整体失败吗?
答案 0 :(得分:2)
这取决于编译器的聪明程度。
在你的情况下,是的,this
肯定会由代表保持活着,只要代表生活。
让我们看看一个肯定不会让this
保持活着的案例:
private void Receive()
{
ATcpState state = this.state;
// create the callback here, in order to use in dynamic
AsyncCallback ReceiveCallback = delegate(IAsyncResult ar)
{
try
{
// Read data from the remote device.
state.BytesReceived = state.Socket.EndReceive(ar);
}
catch (Exception e)
{
// ...
}
};
try
{
state.Socket.BeginReceive(state.Buffer, 0, state.BufferSize, 0,
ReceiveCallback, null);
}
catch (Exception e)
{
// ...
// ...
}
}
然后是编译器优化可能影响集合行为的情况:
private readonly ATcpState state = new ATcpState();
private void Receive()
{
// create the callback here, in order to use in dynamic
AsyncCallback ReceiveCallback = delegate(IAsyncResult ar)
{
try
{
// Read data from the remote device.
state.BytesReceived = state.Socket.EndReceive(ar);
}
catch (Exception e)
{
// ...
}
};
try
{
state.Socket.BeginReceive(state.Buffer, 0, state.BufferSize, 0,
ReceiveCallback, null);
}
catch (Exception e)
{
// ...
// ...
}
}
唯一剩下的问题是,该代表的生命周期是多少?挂起操作是否为root,或者我们只是在委托之间有一个循环引用,可能是this
,state
,state.Socket
和操作?如果这些都不能从根目录中获得,则可以最终确定整个群集(这将关闭套接字,取消操作)。
At least for some objects using the BeginReceive
/EndReceive
pattern, the operation is NOT a root
对于您的案例(Socket.BeginReceive
),在System.Net.Sockets.BaseOverlappedAsyncResult.PinUnmanagedObjects
内创建了一个根。