使用Timer时未激发事件处理程序

本文关键字:事件处理 程序 Timer 使用 | 更新日期: 2023-09-27 17:58:52

我希望只有在需要显示气球提示时才显示系统托盘图标,然后在气球提示关闭时隐藏图标。

然而,一旦图标显示出来,我就无法让它消失,因为事件处理程序没有启动:

public partial class MainWindow : Window {
    public static NotifyIcon trayIcon = new NotifyIcon();
    public MainWindow() {
        InitializeTrayIcon();
    }
    void InitializeTrayIcon() {
        trayIcon.Text = "My App";
        trayIcon.Icon = MyApp.Properties.Resources.myIcon;
        trayIcon.Visible = false;
        //the following never gets fired:
        trayIcon.BalloonTipClosed += (sender, e) => {
            trayIcon.Visible = false; 
        };
      }
      public static void ShowTrayNotification(ToolTipIcon icon, string title, string text, int duration) {
          trayIcon.Visible = true;
          trayIcon.ShowBalloonTip(duration, title, text, icon);
      }
}

ShowTrayNotification()由计时器触发的方法调用:

public abstract class Watcher {
    protected System.Timers.Timer myTimer = new System.Timers.Timer(1000);
    //the following is called in a subclass of Watcher, which is instantiated in MainWindow
    protected void SetupMyTimer() {
        myTimer.AutoReset = true;
        myTimer.Elapsed += myTimer_Elapsed;
        myTimer.Start();
    }
    protected virtual void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) {
        myTimer.Enabled = false;
        MyTimerElapsedCallback();
        myTimer.Enabled = true;
    }
    void MyTimerElapsedCallback() {
        MainWindow.ShowTrayNotification(ToolTipIcon.Info, "Hello There!", "Balloon text here.", 5000);
    }
}

所以气球显示出来了。但是MainWindow中的BalloonTipClosed从未被激发。

我试过:

  • 将(1)NotifyIcon的创建,(2)气球的显示,以及(3)将BalloonTipClosed全部设置在MainWindow中,它工作良好(即BalloonTipClosed被激发)

  • 将(1)、(2)和(3)放入SetupMyTimer()中,也能很好地工作

  • 将(1)、(2)和(3)放入MyTimerElapsedCallback()中,它执行而不是工作(即BalloonTipClosed未发射)

  • 将CCD_ 11更改为CCD_。

  • 使用非lambda BalloonTipClosed EventHandler,是否无效。

因此,我认为问题与Timer有关,但我不知道它是如何影响事件处理程序的,也不知道如何修复。

有什么想法吗?

使用Timer时未激发事件处理程序

如果代码中存在线程错误,则计时器的Elapsed事件将在线程池线程上引发。当你做这种事情时,通常会得到InvalidOperationException,但NotifyIcon没有实现检查。

使其在错误线程上可见的副作用是,在该错误线程上创建了一个用于接收事件通知的隐藏窗口。它根本无法接收任何通知,线程池线程不会引发消息循环。糟糕的诊断,没有例外,也没有很好的方法来解释为什么会出错。

ShowTrayNotification()方法必须使用表单的BeginInvoke()方法,以便代码在UI线程上运行。这很困难,因为该方法是静态的,在绝对必要的情况下,您可以使用Application。OpenForms[0]。BeginInvoke()。但是,最好让Watcher类引发一个事件,而不是直接调用窗体的方法。或者考虑使用一个普通的Winforms‘Timer,你可以在工具箱中找到它。如前所述,Watcher类没有可见的附加值。