2012-01-28 150 views
2

我在while循环中运行一些代码以确保程序始终运行。如果程序没有运行启动它,如果程序是不是有它的副本从备份,然后启动它,没有什么花哨: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); 
} 

问题是每个周期后的内存占用上升大约100KB,这并不是我所知道的,但如果这个运行了一个小时左右,它会导致很大的问题。

我试过暂停它,并使用.Close()的过程,但没有喜悦。任何想法都非常感谢。

+4

是什么让你觉得有内存泄漏?你是否等待GC收集以查看是否收集了一些数据(并因此确实存在内存泄漏)? – ken2k 2012-01-28 11:41:43

+0

你实际上是在第5行使用字符串字面还是是一个错字? – Nuffin 2012-01-28 11:42:34

+0

对不起,错字,固定。 – 2012-01-28 11:43:04

回答

10
  1. 把这些线路的if语句里面,使他们不被执行,除非程序没有运行:

    Process backup = new Process(); 
    ProcessStartInfo check = new ProcessStartInfo(file); 
    
  2. 由于Process工具IDisposable,你可以用它在using语句,如俄德建议。

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

0

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

你可以尝试调用垃圾收集自己使用

System.GC.Collect(); 

注意,这通常被认为是不好的设计,所以你应该只使用这个,如果你确实需要控制的RAM数量迭代的每X量你正在使用。 无论如何,如果你有这样的资源需求,C#可能不是选择的语言。

+2

非常不赞同。你不应该要求GC在大多数情况下明确收集(实际上99%的时间)。 – ken2k 2012-01-28 11:46:50

+0

是的,并且下一个循环将使先前的实例化超出范围,并且内存留下悬浮,无论如何它应该被GCC – Jeb 2012-01-28 11:51:02

+0

我完全同意,并且在OP代码中没有“内存泄漏”(如上所述),然而,如果OP每隔2秒增加100k就会如此担忧,他们可以自行调用GC。我只是在需要的情况下为1%的情况提供此选项,例如资源环境低。 – ose 2012-01-28 12:05:40

0

就像它说了很多,你并没有真正的内存泄漏(至少它看起来不像它)。

但是你可以做的是将你的初始化放置在其他地方,你经常初始化备份并检查你什么时候不需要。

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); 
} 
+0

您还应该将变量的声明更接近其实际用法。 – ken2k 2012-01-28 11:52:51

+0

问题是备份被引用以外的条件,如果有条件我可以移动检查。 – rtpg 2012-01-29 01:08:01

-1

我有同样的问题,所以我用这个:

[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(); 

调用这些方法和内存将被释放。

-1

看!我只是检查了所有这些选项,但没有。另一方面,我解决了你的问题。创建一个新的线程设置它的ApartmentState = STA,然后把你在这段时间内的代码在这个新线程上执行。使用它你将确保所有资源将在线程销毁后释放。我测试了它,它的工作原理!