.Net中内存泄漏的常见原因之一是事件处理程序,它们永远不会从源对象中删除。
此WCF代码是否会导致内存泄漏,或者lambda是否也会超出范围,允许代理类和处理程序进行GC操作?
void AMethod()
{
WCFClient proxy;
proxy = new WCFClient();
proxy.RemoteOperationCompleted += (sender, e) => proxy.Close();
proxy.Open();
proxy.RemoteOperationAsync();
}
答案 0 :(得分:2)
这是我的测试 - 请注意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);
}
}
答案 1 :(得分:1)
不要忘记代理服务器没有正确实现IDisposable。如果发生错误,上面的代码将不会清除连接,并且句柄将保持不变,直到父进程关闭。
答案 2 :(得分:0)
将捕获定义lamdba的上下文,因此将在编译器创建的闭包类中“生存”(您可以使用Reflector查看它们) - 所以您的代理也是如此。使用弱事件处理程序或编写代码进行取消注册。但在这种情况下,你不能使用lambda表达式。
答案 3 :(得分:-1)
那个物体会死......它会被清理干净。
不要忘记lamda没有做任何特别的事情......这是一个编译技巧(所以假设它是正常的+ = SomeDelegate)。
此外,“关闭”方法(我不知道为什么他们没有使它成为IDisposable)将清理剩下的所有其他东西。