【问题标题】:wpf c# tray icon app terminates after 30 minuteswpf c#托盘图标应用程序在30分钟后终止
【发布时间】:2018-06-02 14:37:04
【问题描述】:

以下应用在系统托盘图标中显示磁盘活动。它正常运行大约 30-40 分钟,然后终止,将图标留在桌面上。就好像它被系统作为不必要的后台任务杀死一样。为什么会发生这种情况,我该如何预防?

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);
    }

}

【问题讨论】:

  • Windows 中不存在系统杀死不必要的后台应用程序。
  • 我猜你的应用程序正在泄漏句柄。打开任务管理器,在其中添加“handles”列,找到你的进程并检查数字是否随时间增长。
  • 句柄在 630 到 780 之间变化。
  • FontBrushBitmapGraphics 都实现了 IDisposable 并且您没有正确处理其中的任何一个。此外,您可能希望将 Bitmap 的实例保留更长时间,因为当前 GC 可以在 GetHicon 调用后立即将其杀死,您应该将其设为类成员。
  • Graphics 仍然必须明确处理。如果没有处理,检查还有什么增长。内存?

标签: c# wpf icons systray


【解决方案1】:

转到 App.xaml.cs 并像下面这样实现它。诀窍是永远不要关闭 MainWindow,因为关闭的窗口无法再次显示。而是取消关闭并隐藏它。

using System.ComponentModel;
using System.Windows;

namespace BackgroundApplication
{

    public partial class App : Application
    {
        private System.Windows.Forms.NotifyIcon _notifyIcon;
        private bool _isExit;

        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
            MainWindow = new MainWindow();
            MainWindow.Closing += MainWindow_Closing;

            _notifyIcon = new System.Windows.Forms.NotifyIcon();
            _notifyIcon.DoubleClick += (s, args) => ShowMainWindow();
            _notifyIcon.Icon = BackgroundApplication.Properties.Resources.MyIcon;
            _notifyIcon.Visible = true;

            CreateContextMenu();
        }

        private void CreateContextMenu()
        {
            _notifyIcon.ContextMenuStrip =
              new System.Windows.Forms.ContextMenuStrip();
            _notifyIcon.ContextMenuStrip.Items.Add("MainWindow...").Click += (s, e) => ShowMainWindow();
            _notifyIcon.ContextMenuStrip.Items.Add("Exit").Click += (s, e) => ExitApplication();
        }

        private void ExitApplication()
        {
            _isExit = true;
            MainWindow.Close();
            _notifyIcon.Dispose();
            _notifyIcon = null;
        }

        private void ShowMainWindow()
        {
            if (MainWindow.IsVisible)
            {
                if (MainWindow.WindowState == WindowState.Minimized)
                {
                    MainWindow.WindowState = WindowState.Normal;
                }
                MainWindow.Activate();
            }
            else
            {
                MainWindow.Show();
            }
        }

        private void MainWindow_Closing(object sender, CancelEventArgs e)
        {
            if (!_isExit)
            {
                e.Cancel = true;
                MainWindow.Hide(); // A hidden window can be shown again, a closed one not
            }
        }
    }
}

去App.xaml之外,去掉Startup-Uri,这样在启动应用时,通知区只添加NotifyIcon

<Application x:Class="BackgroundApplication.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:BackgroundApplication">
  <Application.Resources>

    </Application.Resources>
</Application>

取自:

https://www.thomasclaudiushuber.com/2015/08/22/creating-a-background-application-with-wpf/

注意:如果要访问变量,请在 App.xaml.cs 中创建公共只读属性:

public System.Windows.Forms.NotifyIcon NotifyIcon { get { return      _notifyIcon; } }

然后你可以像这样在你的 MainWindow 中使用它:

((App)App.Current).NotifyIcon

【讨论】:

  • 这是一个替代实现。它不能解决问题。查看接受的答案。
【解决方案2】:

此行导致内存泄漏:

hIcon = (bitmapText.GetHicon());

hIcon 需要销毁:

    hIcon = (bitmapText.GetHicon());
    ni.Icon = System.Drawing.Icon.FromHandle(hIcon);
    DestroyIcon(hIcon);

将此代码添加到类中以定义 DestroyIcon:

    [DllImport("user32.dll", SetLastError = true)]
    static extern bool DestroyIcon(IntPtr hIcon);

见:

https://msdn.microsoft.com/en-us/library/system.drawing.icon.fromhandle(v=vs.110).aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多