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

标签 c# asynchronous garbage-collection scope

只是想知道在异步 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/

相关文章:

c# - 针对 x86 和 x64 的设置?

c# - 为什么这些数据绑定(bind)不更新?

c# - WPF 上的嵌套网格问题

c# - 为什么 VS2010 编译器在锁内通过数组的 foreach 迭代中的 yield 会崩溃?

嵌套的 Javascript 异步函数和回调

javascript - EmberJS 异步的过渡到firstObject hasMany

iOS swift : order of code execution/asynchronous execution

Java:与垃圾收集器赛跑

java - 自释放(引用计数)单例

ruby - 针对 Ruby 规范强制 GC