The following app displays disk activity in a systray icon. It runs normally for about 30-40 minutes, and then terminates, leaving the icon on the desktop. It is as if it is being killed by the system as an unnecessary background task. Why is this happening, and how can I prevent it?
public partial class MainWindow : Window
{
public System.Windows.Forms.NotifyIcon ni = new System.Windows.Forms.NotifyIcon();
public MainWindow()
{
InitializeComponent();
ni.Visible = true;
ni.Text = "disktray"; // tooltip text show over tray icon
CreateTextIcon("0");
ni.DoubleClick +=
delegate (object sender, EventArgs args)
{
//this.Show();
//this.WindowState = WindowState.Normal;
ni.Visible = false;
ni.Dispose();
System.Windows.Application.Current.Shutdown();
};
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
CreateTextIcon("0");
DispatcherTimer timer = new DispatcherTimer()
{
Interval = TimeSpan.FromMilliseconds(1024)
};
timer.Tick += Timer_Tick;
timer.Start();
this.Hide();
}
private void Timer_Tick(object sender, EventArgs e)
{
Diskpercent();
string iii = diskpercentvalue.ToString();
CreateTextIcon(iii);
}
public PerformanceCounter myCounter =
new PerformanceCounter("PhysicalDisk", "% Disk Time", "_Total");
public int diskpercentvalue = 0;
public void Diskpercent()
{
var d = Convert.ToInt32(myCounter.NextValue());
if (d > 99) d = 99; // can go over 100%
diskpercentvalue = d;
}
public System.Drawing.Font fontToUse =
new System.Drawing.Font("Microsoft Sans Serif", 16, System.Drawing.FontStyle.Regular, GraphicsUnit.Pixel);
public System.Drawing.Brush brushToUse = new SolidBrush(System.Drawing.Color.White);
public Bitmap bitmapText = new Bitmap(16, 16);
public IntPtr hIcon;
public void CreateTextIcon(string str)
{
//System.Drawing.Font fontToUse = new System.Drawing.Font("Microsoft Sans Serif", 16, System.Drawing.FontStyle.Regular, GraphicsUnit.Pixel);
//System.Drawing.Brush brushToUse = new SolidBrush(System.Drawing.Color.White);
//Bitmap bitmapText = new Bitmap(16, 16);
Graphics g = System.Drawing.Graphics.FromImage(bitmapText);
//IntPtr hIcon;
g.Clear(System.Drawing.Color.Transparent);
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.SingleBitPerPixelGridFit;
g.DrawString(str, fontToUse, brushToUse, -4, -2);
hIcon = (bitmapText.GetHicon());
ni.Icon = System.Drawing.Icon.FromHandle(hIcon);
}
}
This line is causing a memory leak:
hIcon = (bitmapText.GetHicon());
hIcon needs to be destroyed:
hIcon = (bitmapText.GetHicon());
ni.Icon = System.Drawing.Icon.FromHandle(hIcon);
DestroyIcon(hIcon);
Add this code to the class to define DestroyIcon:
[DllImport("user32.dll", SetLastError = true)]
static extern bool DestroyIcon(IntPtr hIcon);
see:
https://msdn.microsoft.com/en-us/library/system.drawing.icon.fromhandle(v=vs.110).aspx