循环时内存泄漏

本文关键字:泄漏 内存 循环 | 更新日期: 2023-09-27 18:21:36

我正在while循环中运行一些代码,以确保程序始终在运行。如果程序没有运行,它会启动它,如果程序不在那里,它会从备份中复制它,然后启动它,没什么奇怪的:

while (true)
{
    Process backup = new Process();
    ProcessStartInfo check = new ProcessStartInfo(file);
    if (Process.GetProcessesByName(file).Length == 0)
    {
        if(File.Exists(file))
        {
            backup.StartInfo = check;
            backup.Start();
        }
        else if (!File.Exists(file))
        {
            File.Copy(backupFile, file);
            Thread.Sleep(250);
            backup.StartInfo = check;
            backup.Start();
        }
    }
    backup.Close();
    Thread.Sleep(2000);
}

问题是,在每个周期之后,ram的使用量会增加大约100KB,我知道这不是很多,但如果运行一个小时左右,就会导致大问题。

我试过暂停它,并在这个过程中使用.Close(),但没有乐趣。任何想法都将不胜感激。

循环时内存泄漏

  1. 将这些行放在if语句中,以便除非进程未运行,否则不会执行它们:

    Process backup = new Process();
    ProcessStartInfo check = new ProcessStartInfo(file);
    
  2. 由于Process实现了IDisposable,因此可以将其封装在using语句中,正如Oded所建议的那样。

  3. 您没有实际的内存泄漏。当垃圾收集器运行时,内存将被回收。如果临时内存使用是一个问题,您可以强制GC运行,但我认为一旦执行#1,您也不会遇到临时内存使用的问题。

就像前面说的那样,你并没有真正发生内存泄漏(至少看起来不是这样)。

但你可以做的是把初始化放在其他地方,你经常在不需要的时候初始化备份和检查

while (true)
{
    Process backup;
    ProcessStartInfo check;
    if (Process.GetProcessesByName(file).Length == 0)
    {
        check = new ProcessStartInfo(file);//moved init
        backup = new Process();//moved init
        if(File.Exists(file))
        {
            backup.StartInfo = check;
            backup.Start();
        }
        else if (!File.Exists(file))
        {
            File.Copy(backupFile, file);
            Thread.Sleep(250);
            backup.StartInfo = check;
            backup.Start();
        }
    }
    backup.Close();
    Thread.Sleep(2000);
}

您发布的代码中没有内存泄漏。

您可以尝试使用每X次迭代调用一次垃圾收集器

System.GC.Collect();

请注意,这通常被认为是糟糕的设计,因此只有当您绝对需要控制正在使用的RAM数量时,才应该使用它。在任何情况下,如果您有这样的硬资源需求,C#可能不是您选择的语言。

我遇到了同样的问题,所以我使用了这个:

[DllImport("KERNEL32.DLL", EntryPoint = "SetProcessWorkingSetSize", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern bool SetProcessWorkingSetSize(IntPtr pProcess, int dwMinimumWorkingSetSize, int dwMaximumWorkingSetSize);
[DllImport("KERNEL32.DLL", EntryPoint = "GetCurrentProcess", SetLastError = true, CallingConvention = CallingConvention.StdCall)]
internal static extern IntPtr GetCurrentProcess();

调用这些方法,内存就会被释放。

看!,我只是检查了所有的选项,但什么都没有。另一方面,我解决了你的问题。创建一个新线程,将其ApartmentState=STA设置为空,然后将您在其中的代码放在这个新线程上执行。使用它,您将确保所有资源将在线程销毁后释放。我测试过了,它有效!