0

I have a small, simple C# application which updates an icon in the system tray. I use it to graphically show the CPU usage. The application works great. I keep the Window hidden and don't show it in the taskbar so it doesn't get in the way.

My issue is that it will run great for a while. Often several hours. But then it will mysteriously quit. No warnings. Nothing. The icon is just gone and the program is no longer running. I have tested the program in the debugger under varying conditions, so I don't think that is it. Is there something obvious I am missing? If the program encounters an error and quits should I be expecting a message if the Form is hidden? Is there some "keep-alive" message or something that I need to handle?

Here is the relevant section of code:

public Form1()
{
    InitializeComponent();

    trayIcon = new NotifyIcon();
    trayIcon.Text = "CPU Utilization";
    trayIcon.Icon = new Icon(SystemIcons.Application, 40, 40);

    trayIcon.Visible = true;

    update = new Thread(new ThreadStart(UpdateCPU));
    update.Start();
}

protected override void OnLoad(EventArgs e)
{
    Visible = false;
    ShowInTaskbar = false;

    base.OnLoad(e);
}

private void UpdateCPU()
{
    Bitmap bm = new Bitmap(32, 32);
    Graphics g = Graphics.FromImage(bm);

    while (true)
    {
        g.FillRectangle(new SolidBrush(c3), 17, 17, 15, 15);
        trayIcon.Icon = System.Drawing.Icon.FromHandle(bm.GetHicon());

        Thread.Sleep(1000);
    }
}

Any help would be greatly appreciated!

  • 2
    Check the Event Viewer system tool and look for the error log for your application. Maybe there's a crash report or a warning. Second thing - check the Task Manager and see if your process allocates too much memory. I understand there's a GC and stuff but the Icon.FromHandle() call looks suspicious. – Viktor Latypov Jun 27 '12 at 21:31
  • 1
    Not to be sarcastic, but are you *sure* it's terminated and not just hidden by Microsoft's auto-hide systray icons functionality? – adelphus Jun 27 '12 at 21:56
  • The system wasn't totally out of memory, if that's what you meant. It was only using 1 GB / 8 GB. I have implemented Sean's suggestion to fix the FromHandle() issue anyway though. – user1376232 Jun 27 '12 at 22:08
  • And yes, I'm sure it was terminated. I double-checked the auto-hide first thing. – user1376232 Jun 27 '12 at 22:09

2 Answers2

1

I would suggest you add an Unhandled Exception Handler

Global Exception Handling for winforms control

An Exception is likely being thrown, causing your program to exit.

Then, introduce logging to log what the Exception was. Personally I prefer NLog.

I'm a bit surprised that you can update trayIcon from a non-UI thread without receiving a cross-thread exception.

Community
  • 1
  • 1
Eric J.
  • 147,927
  • 63
  • 340
  • 553
  • Thanks. I didn't think about whether or not to use the UI thread, and I know that cross-threading can give inconsistent results. I'll try running it without threads and see if that works. – user1376232 Jun 27 '12 at 21:56
  • Rather than run without threads, just use a delegate to update your UI thread. See the following link for a most excellent extension method that makes invoking on the UI thread from another thread a real breeze: http://stackoverflow.com/a/3588137/141172 – Eric J. Jun 27 '12 at 22:27
0

The documentation seems to agree with Viktor Latypov's comment, you should be doing something like this:

Icon newIcon = Icon.FromHandle(bm.GetHicon());

trayIcon.Icon = newIcon;

DestroyIcon(newIcon.Handle);
Sean Bright
  • 118,630
  • 17
  • 138
  • 146