C# 为什么我的示例代码中存在内存泄漏?

C# 为什么我的示例代码中存在内存泄漏?,c#,.net,memory-leaks,C#,.net,Memory Leaks,您的值只是在后台创建的其他内容的固定成本开销,如果您在程序中运行两次测试,则第二次和任何其他后续运行将有0字节的更改 在代码上运行内存分析器发现7590的大部分是Console.WriteLine()内部使用的TextWriter的内部string和char[]缓冲区 这是一个经过调整的测试版本,在我的机器上运行第二次测试时返回0 Value changed: 153 Is raiser alive? False Is subscriber alive? False Memory size (b

您的值只是在后台创建的其他内容的固定成本开销,如果您在程序中运行两次测试,则第二次和任何其他后续运行将有0字节的更改

在代码上运行内存分析器发现7590的大部分是
Console.WriteLine()
内部使用的
TextWriter
的内部
string
char[]
缓冲区

这是一个经过调整的测试版本,在我的机器上运行第二次测试时返回0

Value changed: 153
Is raiser alive? False
Is subscriber alive? False
Memory size (bytes):
- before : 21960
- after : 29520
=> Leak: 7560
使用系统;
使用系统线程;
公共课程
{
公共静态void Main(字符串[]args)
{
RunTest();
RunTest();
}
私有静态void RunTest()
{
//WeakReference wfRaiser;
//弱引用;
var before=GC.GetTotalMemory(true);
//区域1:提高者的范围
{
var raiser=新的raiser();
//wfRaiser=新WeakReference(raiser);
//区域2:用户范围
{
var subscriber=新订户();
//wfSubscriber=新的WeakReference(订户);
raiser.ValueChanged+=subscriber.HandlingMethod;
}
raiser.设定值(153);
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
var after=GC.GetTotalMemory(true);
Console.WriteLine(//$“raiser是否处于活动状态?{wfRaiser.IsAlive}\n”+
//$“订阅服务器是否处于活动状态?{wfSubscriber.IsAlive}\n”+
“内存大小(字节):\n”+
$“-before:{before}\n”+
$“-after:{after}\n”+
$“=>泄漏:{after-before}”);
}
}
公开募捐者
{
公共事件处理程序值已更改;
public void SetValue(int值)=>ValueChanged?.Invoke(此,值);
}
公共类订户
{
私有只读双精度[]MyData=新双精度[9999];
public void HandlingMethod(object sender,int value)=>Console.WriteLine($“value changed:{value}”);
}

也许wfRaiser和wfSubscriber使用的内存可能导致了一些内存泄漏?@anthonycgrath我不这么认为。即使我删除了那些弱引用,结果仍然是一样的。谢谢。你是对的。当将代码提取到方法中并多次调用它时,只有第一次运行产生内存泄漏,下面的运行显示24个字节的更改。将
线程.Sleep
s替换为
GC.Collect();GC.WaitForPendingFinalizers();GC.Collect()并去掉两个弱引用对象,在第一个对象之后的运行将得到0。
Value changed: 153
Is raiser alive? False
Is subscriber alive? False
Memory size (bytes):
- before : 21960
- after : 29520
=> Leak: 7560
using System;
using System.Threading;

public class Program
{
    public static void Main(string[] args)
    {
        RunTest();
        RunTest();
    }

    private static void RunTest()
    {
        //WeakReference wfRaiser;
        //WeakReference wfSubscriber;

        var before = GC.GetTotalMemory(true);

        //region 1: scope of raiser
        {
            var raiser = new Raiser();
            //wfRaiser = new WeakReference(raiser);
            //region 2: scope of subscriber
            {
                var subscriber = new Subscriber();
                //wfSubscriber = new WeakReference(subscriber);
                raiser.ValueChanged += subscriber.HandlingMethod;
            }

            raiser.SetValue(153);
        }

        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        var after = GC.GetTotalMemory(true);

        Console.WriteLine(//$"Is raiser alive? {wfRaiser.IsAlive}\n" +
                          //$"Is subscriber alive? {wfSubscriber.IsAlive}\n" +
                          "Memory size (bytes):\n" +
                          $"- before : {before} \n" +
                          $"- after : {after}\n" +
                          $"=> Leak: {after - before}");
    }
}

public class Raiser
{
    public event EventHandler<int> ValueChanged;
    public void SetValue(int value) => ValueChanged?.Invoke(this, value);
}

public class Subscriber
{
    private readonly double[] MyData = new double[9999];
    public void HandlingMethod(object sender, int value) => Console.WriteLine($"Value changed: {value}");
}