Can delegates cause a memory leak? GC.TotalMemory(true) seems to indicate so(委托会导致内存泄漏吗?GC.TotalMemory(true) 似乎表明了这一点)
问题描述
代码
using System;
internal static class Test
{
private static void Main()
{
try
{
Console.WriteLine("{0,10}: Start point", GC.GetTotalMemory(true));
Action simpleDelegate = SimpleDelegate;
Console.WriteLine("{0,10}: Simple delegate created", GC.GetTotalMemory(true));
Action simpleCombinedDelegate = simpleDelegate + simpleDelegate + simpleDelegate;
Console.WriteLine("{0,10}: Simple combined delegate created", GC.GetTotalMemory(true));
byte[] bigManagedResource = new byte[100000000];
Console.WriteLine("{0,10}: Big managed resource created", GC.GetTotalMemory(true));
Action bigManagedResourceDelegate = bigManagedResource.BigManagedResourceDelegate;
Console.WriteLine("{0,10}: Big managed resource delegate created", GC.GetTotalMemory(true));
Action bigCombinedDelegate = simpleCombinedDelegate + bigManagedResourceDelegate;
Console.WriteLine("{0,10}: Big combined delegate created", GC.GetTotalMemory(true));
GC.KeepAlive(bigManagedResource);
bigManagedResource = null;
GC.KeepAlive(bigManagedResourceDelegate);
bigManagedResourceDelegate = null;
GC.KeepAlive(bigCombinedDelegate);
bigCombinedDelegate = null;
Console.WriteLine("{0,10}: Big managed resource, big managed resource delegate and big combined delegate removed, but memory not freed", GC.GetTotalMemory(true));
GC.KeepAlive(simpleCombinedDelegate);
simpleCombinedDelegate = null;
Console.WriteLine("{0,10}: Simple combined delegate removed, memory freed, at last", GC.GetTotalMemory(true));
GC.KeepAlive(simpleDelegate);
simpleDelegate = null;
Console.WriteLine("{0,10}: Simple delegate removed", GC.GetTotalMemory(true));
}
catch (Exception e)
{
Console.WriteLine(e);
}
Console.ReadKey(true);
}
private static void SimpleDelegate() { }
private static void BigManagedResourceDelegate(this byte[] array) { }
}
输出
GC.TotalMemory(true)
105776: Start point
191264: Simple delegate created
191328: Simple combined delegate created
100191344: Big managed resource created
100191780: Big managed resource delegate created
100191812: Big combined delegate created
100191780: Big managed resource, big managed resource delegate and big combined delegate removed, but memory not freed
191668: Simple combined delegate removed, memory freed, at last
191636: Simple delegate removed
推荐答案
有趣的案例.这是解决方案:
Interesting case. Here is the solution:
组合委托是观察上纯粹的:看起来委托对外部来说是不可变的.但是在内部,正在修改现有的代表.出于性能原因,它们在某些条件下共享相同的 _invocationList
(针对少数委托连接到同一事件的场景进行优化).不幸的是,simpleCombinedDelegate
的 _invocationList
引用了导致内存保持活动状态的 bigMgdResDelegate
.
Combining delegates is observationally pure: It looks like delegates are immutable to the outside. But internally, existing delegates are being modified. They share, under certain conditions, the same _invocationList
for performance reasons (optimizing for the scenario that a few delegates are hooked up to the same event). Unfortunately, the _invocationList
for the simpleCombinedDelegate
references the bigMgdResDelegate
which causes the memory to be kept alive.
这篇关于委托会导致内存泄漏吗?GC.TotalMemory(true) 似乎表明了这一点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:委托会导致内存泄漏吗?GC.TotalMemory(true) 似乎表明了这一点
- 输入按键事件处理程序 2022-01-01
- 在哪里可以找到使用中的C#/XML文档注释的好例子? 2022-01-01
- Web Api 中的 Swagger .netcore 3.1,使用 swagger UI 设置日期时间格式 2022-01-01
- 带有服务/守护程序应用程序的 Microsoft Graph CSharp SDK 和 OneDrive for Business - 配额方面返回 null 2022-01-01
- MoreLinq maxBy vs LINQ max + where 2022-01-01
- 良好实践:如何重用 .csproj 和 .sln 文件来为 CI 创建 2022-01-01
- C# 中多线程网络服务器的模式 2022-01-01
- C#MongoDB使用Builders查找派生对象 2022-09-04
- 如何用自己压缩一个 IEnumerable 2022-01-01
- WebMatrix WebSecurity PasswordSalt 2022-01-01