此 WCF 客户端代码会导致内存泄漏吗?

发布于 2024-07-08 08:45:43 字数 326 浏览 8 评论 0原文

.Net 中内存泄漏的常见原因之一是事件处理程序从未从其源对象中删除。

此 WCF 代码是否会导致内存泄漏,或者 lambda 是否也会超出范围,从而允许代理类和处理程序被 GC ?

void AMethod()
{
    WCFClient proxy;
    proxy = new WCFClient();
    proxy.RemoteOperationCompleted += (sender, e) => proxy.Close();
    proxy.Open();
    proxy.RemoteOperationAsync();
}

One of the frequent causes of memory leaks in .Net are event handlers which are never removed from their source objects.

Will this WCF code cause a memory leak, or will the lambda go out of scope too, allowing both the proxy class and the handler to be GCed?

void AMethod()
{
    WCFClient proxy;
    proxy = new WCFClient();
    proxy.RemoteOperationCompleted += (sender, e) => proxy.Close();
    proxy.Open();
    proxy.RemoteOperationAsync();
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

心凉 2024-07-15 08:45:43

这是我的测试 - 请注意 lambda 中的显式 proxy 设置为 null - 如果没有它,WeakReference 就会存在,因此可能会发生泄漏:

public class Proxy
{
    private bool _isOpen;

    public event EventHandler Complete;

    public void Close() 
    {
        _isOpen = false;
    }

    public void Open() 
    { 
        _isOpen = true; 
    }

    public void RemoteOperationAsync()
    {
        if (!_isOpen)
            throw new ApplicationException();
        Thread.Sleep(1000);
        if (Complete != null)
            Complete(this, EventArgs.Empty);
    }
}

public static class Program
{
    public static void Main()
    {
        WeakReference wr = null;

        {
            var proxy = new Proxy();
            proxy.Complete += (sender, e) =>
                {
                    proxy.Close();
                    wr = new WeakReference(proxy);
                    proxy = null;
                };
            proxy.Open();
            proxy.RemoteOperationAsync();
        }

        GC.Collect(GC.GetGeneration(wr));
        GC.WaitForPendingFinalizers();

        Console.WriteLine("[LAMBDA] Is WeakReference alive? " + wr.IsAlive);
    }
}

Here's my test - note the explicit proxy set to null in the lambda - without it the WeakReference lives and therefore a leak is likely:

public class Proxy
{
    private bool _isOpen;

    public event EventHandler Complete;

    public void Close() 
    {
        _isOpen = false;
    }

    public void Open() 
    { 
        _isOpen = true; 
    }

    public void RemoteOperationAsync()
    {
        if (!_isOpen)
            throw new ApplicationException();
        Thread.Sleep(1000);
        if (Complete != null)
            Complete(this, EventArgs.Empty);
    }
}

public static class Program
{
    public static void Main()
    {
        WeakReference wr = null;

        {
            var proxy = new Proxy();
            proxy.Complete += (sender, e) =>
                {
                    proxy.Close();
                    wr = new WeakReference(proxy);
                    proxy = null;
                };
            proxy.Open();
            proxy.RemoteOperationAsync();
        }

        GC.Collect(GC.GetGeneration(wr));
        GC.WaitForPendingFinalizers();

        Console.WriteLine("[LAMBDA] Is WeakReference alive? " + wr.IsAlive);
    }
}
独守阴晴ぅ圆缺 2024-07-15 08:45:43

不要忘记代理没有正确实现 IDisposable。 如果发生错误,上面的代码将不会清理连接,并且句柄将保留到父进程关闭为止。

Don't forget that the proxy's don't correctly implement IDisposable. If an error occurs the code above will not clean up the connection and the handle will remain until the parent process is closed.

落日海湾 2024-07-15 08:45:43

定义 lamdba 的上下文将被捕获,因此将在编译器创建的闭包类中“生存”(您可以使用 Reflector 看到它们) - 所以您的代理也是如此。 使用弱事件处理程序或编写注销代码。 但在这种情况下你不能使用 lambda 表达式。

The context where the lamdba is defined will be captured and will therefore "survive" in the compiler created closure class (you can see them with Reflector) - so your proxy too. Use weak event handler or write code for unregistration. But in that case you can't use lambda expression.

沦落红尘 2024-07-15 08:45:43

那个物体会死……它会被清理掉。

不要忘记 lamda 没有做任何特殊的事情......这是一个编译器技巧(所以假设它是一个正常的 += SomeDelegate)。

另外,“Close”方法(我不知道为什么他们没有将其设为 IDisposable)将清除所有其他打开的内容。

That object will die... it'll be cleaned up.

Don't forget that the lamda isn't doing anything special... it's a compiler trick (so just assume it's a normal += SomeDelegate).

Also, the "Close" method (I don't know why they didn't make it IDisposable) will clean up everything else that was left open.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文