[英]Simple C# application eating memory
好吧,基本上,我在具有一个计时器的系统托盘中运行了这个简单的应用程序。 每次打勾时,它都会检查以查看给定的目录和文件是否存在,并根据结果更改其图标。
问题在于,每个计时器都会为应用程序的内存增加约100kb。 我目前正在运行它大约5分钟,它已经使用了40MB的内存,这对于这种“微型”应用程序是不可接受的。
这是我的代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
namespace Tray
{
public partial class Main : Form
{
string drive = "C:\\";
string file = "test.txt";
System.Drawing.Image imgRed = Image.FromFile("res\\icon-red.png");
System.Drawing.Image imgOrange = Image.FromFile("res\\icon-orange.png");
System.Drawing.Image imgGreen = Image.FromFile("res\\icon-green.png");
System.Drawing.Icon icoRed = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-red.ico");
System.Drawing.Icon icoOrange = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-orange.ico");
System.Drawing.Icon icoGreen = System.Drawing.Icon.ExtractAssociatedIcon("res\\icon-green.ico");
public Main()
{
InitializeComponent();
}
public static string ShowPrompt(string text, string caption)
{
Form prompt = new Form();
prompt.Width = 500;
prompt.Height = 150;
prompt.Text = caption;
Label textLabel = new Label() { Left = 50, Top = 20, Text = text };
TextBox textBox = new TextBox() { Left = 50, Top = 50, Width = 400 };
Button confirmation = new Button() { Text = "Ok", Left = 350, Width = 100, Top = 70 };
confirmation.Click += (sender, e) => { prompt.Close(); };
prompt.Controls.Add(confirmation);
prompt.Controls.Add(textLabel);
prompt.Controls.Add(textBox);
prompt.ShowDialog();
return textBox.Text;
}
public void updateInfo(){
this.statusDrive.Text = "Drive [" + drive + "]";
this.statusFile.Text = "File [" + drive + file + "]";
}
public void exec(){
int status = 0;
this.trayIcon.Text = "[Drive - ";
if (Directory.Exists(drive)){
this.statusDrive.Text += " - OK";
this.statusDrive.Image = imgGreen;
status++;
this.trayIcon.Text += "OK] ";
} else{
this.statusDrive.Text += " - FAIL";
this.statusDrive.Image = imgRed;
this.trayIcon.Text += "FAIL] ";
}
this.trayIcon.Text += "[File - ";
if (File.Exists(drive + file))
{
this.statusFile.Text += " - OK";
this.statusFile.Image = imgGreen;
status++;
this.trayIcon.Text += "OK] ";
}
else
{
this.statusFile.Text += " - FAIL";
this.statusFile.Image = imgRed;
this.trayIcon.Text += "FAIL] ";
}
switch (status)
{
case 2:
this.Icon = icoGreen;
this.trayIcon.Icon = icoGreen;
this.status.Image = imgGreen;
break;
case 1:
this.Icon = icoOrange;
this.trayIcon.Icon = icoOrange;
this.status.Image = imgOrange;
break;
case 0:
default:
this.Icon = icoRed;
this.trayIcon.Icon = icoRed;
this.status.Image = imgRed;
break;
}
}
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
}
private void timer1_Tick(object sender, EventArgs e)
{
updateInfo();
exec();
}
private void chDrive_Click(object sender, EventArgs e)
{
this.drive = ShowPrompt("Enter drive path", "Change drive");
}
private void chFile_Click(object sender, EventArgs e)
{
this.file = ShowPrompt("Enter new file path:", "Change file");
}
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
}
}
我已经尝试通过将图标和图像预加载到变量中并将它们分配给适当的属性来优化应用程序,但是这并不能解决我的问题。
另外,请注意,通过执行以下操作(在Program.cs中),我设法隐藏了主窗口:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace Tray
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Main mForm = new Main();
Application.Run();
}
}
}
我只是注意到内存使用量上升到50MB,然后下降到20MB(然后又上升)。 这是我可能解决的问题,还是Windows的“问题”?
您似乎从来没有在ShowPrompt
正确地ShowPrompt
,所以我想这是您的问题。
因为未关闭显示为对话框的表单,所以当应用程序不再需要该表单时,必须调用该表单的Dispose方法。
我要刺痛一下,它是每秒发生一次字符串串联。 考虑使用StringBuilder
。 40MB确实不是什么。
RE:您的更新。 垃圾收集器正在回收它认为合适的内存。
垃圾收集器将为您完成所有内存管理工作。 内存的临时增加并不总是意味着内存泄漏。 GC收集内存时,它可能会下降。 如果您怀疑内存泄漏,则需要进行内存分析,这并非易事。 您需要阅读本文以获取可用来发现代码中问题的步骤。 或者,市场上有多种工具可以为您完成这项工作。 您可以使用Red Gate的Ants Profiler , memprofiler等。
可能会减少内存使用的一些要点:
尝试预构建您正在exec()中构建的所有那些字符串。 看起来它们都是运行时常量,但是您在每个滴答声中都构建它们,而不是在应用程序启动时构建它们。 如果不可能,请使用StringBuilder而不是+ =。
仅在发生更改的情况下更改控件的属性(图标,trayText等)。 IE,如果纸盘文本已经是“ [Drive C:\\-OK]”,则不要在下一个刻度上再次将其值设置为“ [Drive C:\\-OK]”。
您可能会考虑的一件事不是使用计时器,而是为什么不使用FileSystemWatcher并附加到事件:
var watcher = new FileSystemWatcher("somepath");
watcher.Deleted += (sender, eventArgs) => { };
watcher.Changed += (sender, eventArgs) => { };
watcher.Error += (sender, eventArgs) => { };
watcher.Renamed += (sender, eventArgs) => { };
我也同意,一旦处理完表格,就应该将其丢弃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.