gpt4 book ai didi

C# 异步 TCP 及其闭包引用实例的垃圾回收?

转载 作者:行者123 更新时间:2023-11-30 17:19:03 24 4
gpt4 key购买 nike

只是想知道在异步 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();
}

实例会不会是导致 Receive() 整体失败的 GC?

最佳答案

这取决于编译器的聪明程度。

在您的情况下,是的,this 肯定会由委托(delegate)人保持事件状态,只要委托(delegate)人还活着。

让我们看一个绝对不会让 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)
{
// ...
// ...
}
}

剩下的唯一问题是,该代表的生命周期是多少?挂起的操作是一个根,还是我们只是在委托(delegate)之间有一个循环引用,可能是 thisstatestate.Socket 和手术?如果这些都不能从根访问,那么可以完成整个束(这将关闭套接字,取消操作)。

At least for some objects using the BeginReceive/EndReceive pattern, the operation is NOT a root

对于您的案例 (Socket.BeginReceive),它看起来像是在 System.Net.Sockets.BaseOverlappedAsyncResult.PinUnmanagedObjects 中创建了一个根。

关于C# 异步 TCP 及其闭包引用实例的垃圾回收?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5222575/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com