使用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有关,但我不知道它是如何影响事件处理程序的,也不知道如何修复。
有什么想法吗?
如果代码中存在线程错误,则计时器的Elapsed事件将在线程池线程上引发。当你做这种事情时,通常会得到InvalidOperationException,但NotifyIcon没有实现检查。
使其在错误线程上可见的副作用是,在该错误线程上创建了一个用于接收事件通知的隐藏窗口。它根本无法接收任何通知,线程池线程不会引发消息循环。糟糕的诊断,没有例外,也没有很好的方法来解释为什么会出错。
ShowTrayNotification()方法必须使用表单的BeginInvoke()方法,以便代码在UI线程上运行。这很困难,因为该方法是静态的,在绝对必要的情况下,您可以使用Application。OpenForms[0]。BeginInvoke()。但是,最好让Watcher类引发一个事件,而不是直接调用窗体的方法。或者考虑使用一个普通的Winforms‘Timer,你可以在工具箱中找到它。如前所述,Watcher类没有可见的附加值。