0

基本的に、タイマーが 1 つあるシステム トレイでこの単純なアプリケーションを実行しています。ティックごとに、指定されたディレクトリとファイルが存在するかどうかを確認し、その結果に基づいてアイコンを変更します。

問題は、すべてのタイマー ティックがアプリケーションのメモリを 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 の「問題」ですか?

4

5 に答える 5

1

ガベージ コレクターは、メモリ管理のすべての作業を行います。メモリの一時的な増加は、常にメモリ リークがあることを意味するわけではありません。GC がメモリを収集すると、ダウンする可能性があります。メモリ リークが疑われる場合は、簡単な作業ではないメモリ プロファイリングを行う必要があります。コードの問題を見つけるために実行できる手順については、この記事を読む必要があります。または、この作業を行うための複数のツールが市場に出回っています。Red Gate のAnts プロファイラーmemprofilerなどを使用できます。

于 2013-07-19T14:58:38.150 に答える
0

考えられることの 1 つは、タイマーを使用するのではなく、FileSystemWatcher を使用してイベントにアタッチしないことです。

var watcher = new FileSystemWatcher("somepath");
watcher.Deleted += (sender, eventArgs) => { };
watcher.Changed += (sender, eventArgs) => { };
watcher.Error += (sender, eventArgs) => { };
watcher.Renamed += (sender, eventArgs) => { };

また、使い終わったらフォームを破棄する必要があることに同意します。

于 2013-07-19T16:46:00.077 に答える