c#windows服务内存问题(内存泄漏?)
我对用C#(framework 3.5,visual studio 2008)编写的Windows服务中的内存管理有点问题 该服务运行良好,有一个计时器和一个回调,每3分钟启动一次该过程。 因此,Windows任务管理器中的内存在每次计时器运行时都会缓慢增长 你有办法解决这个问题吗 为了简化问题,下面是一个非常简单的代码,它存在相同的问题:c#windows服务内存问题(内存泄漏?),c#,memory,memory-leaks,timer,C#,Memory,Memory Leaks,Timer,我对用C#(framework 3.5,visual studio 2008)编写的Windows服务中的内存管理有点问题 该服务运行良好,有一个计时器和一个回调,每3分钟启动一次该过程。 因此,Windows任务管理器中的内存在每次计时器运行时都会缓慢增长 你有办法解决这个问题吗 为了简化问题,下面是一个非常简单的代码,它存在相同的问题: using System; using System.Collections.Generic; using System.ComponentModel; u
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.IO;
namespace svcTest
{
public partial class svcTest : ServiceBase
{
private Timer tmr;
private TimerCallback tmrCallBack;
public svcTest()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
FileStream fs = new FileStream(@"c:\svclog.txt", FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter m_streamWriter = new StreamWriter(fs);
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine("Service Started on " + DateTime.Now.ToLongDateString() + " at " + DateTime.Now.ToLongTimeString());
m_streamWriter.WriteLine(" *----------------*");
m_streamWriter.Flush();
m_streamWriter.Close();
tmrCallBack = new TimerCallback(goEXE);
tmr = new Timer(tmrCallBack, null, 0, 1000 * 60 * 1 / 2);
}
protected override void OnStop()
{
FileStream fs = new FileStream(@"c:\svclog.txt", FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter m_streamWriter = new StreamWriter(fs);
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine("Service Stopped on " + DateTime.Now.ToLongDateString() + " at " + DateTime.Now.ToLongTimeString());
m_streamWriter.WriteLine(" *----------------*");
m_streamWriter.Flush();
m_streamWriter.Close();
tmr.Dispose();
}
private void goEXE(Object state)
{
Console.WriteLine(DateTime.Now.ToString());
FileStream fs = new FileStream(@"c:\svclog.txt", FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter m_streamWriter = new StreamWriter(fs);
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine("Service running on " + DateTime.Now.ToLongDateString() + " at " + DateTime.Now.ToLongTimeString());
m_streamWriter.WriteLine(" *----------------*");
m_streamWriter.Flush();
m_streamWriter.Close();
}
}
}
任何帮助都将不胜感激
stefano您没有处理
文件流
。垃圾收集器可以为您调用Dispose()
,但这是不确定的(即,您不知道何时/是否会发生)。这里可能已经决定不再麻烦了。因此,推荐的最佳实践是考虑使用语句:在<代码>中实现实现<代码> IDISPABLE < /C> >的任何内容:
using (FileStream fs = new FileStream(@"c:\svclog.txt", FileMode.OpenOrCreate, FileAccess.Write)
{
using (using (StreamWriter m_streamWriter = new StreamWriter(fs)))
{
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine("Service Started on " + DateTime.Now.ToLongDateString() + " at " + DateTime.Now.ToLongTimeString());
m_streamWriter.WriteLine(" *----------------*");
}
}
维护和原因,还应考虑将文件编写代码重构为单独的方法:
private void Log(string message)
{
using (FileStream fs = new FileStream(@"c:\svclog.txt", FileMode.OpenOrCreate, FileAccess.Write)
{
using (using (StreamWriter m_streamWriter = new StreamWriter(fs)))
{
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine(message + " " + DateTime.Now.ToLongDateString() + " at " + DateTime.Now.ToLongTimeString());
m_streamWriter.WriteLine(" *----------------*");
}
}
}
protected override void OnStart(string[] args)
{
Log("Service Started");
tmrCallBack = new TimerCallback(goEXE);
tmr = new Timer(tmrCallBack, null, 0, 1000 * 60 * 1 / 2);
}
protected override void OnStop()
{
Log("Service Stopped");
tmr.Dispose();
}
private void goEXE(Object state)
{
Console.WriteLine(DateTime.Now.ToString());
Log("Service running");
}
我假设您的文件不断增长,因为您添加了新行 最后,streamwriter会消耗更多内存 我宁愿在程序启动时创建一个流编写器 而不是在回调时做。但是你会锁定一个文件
通过您的服务。此外,当达到某些最佳参数时,.NET会运行垃圾收集。如果系统没有在内存不足的情况下运行,它可能会认为运行GC.Collect代价太高,因此您的非引用但仍在内存中的对象将继续保持这种状态。使用
文件.AppendAllText(路径、内容)代码>这是最好的,它将处理所有内存泄漏。私有void goEXE(对象状态){…与上面的代码相同…m_streamWriter.Dispose();fs.Dispose();}尼斯刚刚使用streamWriter修复了内存泄漏!谢谢!为什么在StreamWriter上使用嵌套?我四处搜索,但没有找到答案。仅仅因为它实现了IDisposable
处理一次性对象是最佳实践。您可以将其设置为私有字段或其他内容,并将其保留,仅在父对象本身被处理时才处理它,但这并不是这个答案的真正意义。
public class Logger : IDisposable
{
public void Log(string message)
{
using (FileStream fs = new FileStream(@"c:\svclog.txt", FileMode.OpenOrCreate, FileAccess.Write)
{
using (using (StreamWriter m_streamWriter = new StreamWriter(fs)))
{
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine(message + " " + DateTime.Now.ToLongDateString() + " at " + DateTime.Now.ToLongTimeString());
m_streamWriter.WriteLine(" *----------------*");
}
}
}
public void Dispose()
{
GC.SuppressFinalize(this);
}
}