【发布时间】:2016-08-10 11:29:25
【问题描述】:
我的应用需要不时显示气球通知。我通过Dispatcher.Invoke() 执行此操作,该Action 创建NotifyIcon,显示气球通知,然后释放系统托盘图标。
public abstract class Foo {
void Bar() {
MainWindow.ShowTrayNotification(ToolTipIcon.Info, "Hello There!", "Balloon text here.");
}
}
public partial class MainWindow : Window {
static Dispatcher dispatcher = System.Windows.Threading.Dispatcher.CurrentDispatcher;
public static void ShowTrayNotification(ToolTipIcon icon, string title, string text) {
dispatcher.Invoke(new Action(() => {
//anything here is not run
UIHelper.ShowTrayNotification(icon, title, text); //static method
}));
//anything here is also not called if dispatcher.Invoke() is not run
}
}
但是,有时Dispatcher.Invoke 不会运行。日志记录在它之前停止,并且在Invoke 的Action 内不会发生任何日志记录。
奇怪的是,当我触发 PC 关机时,突然Invoke 被触发(显示通知)并正常进行(执行我的关机前回调)。
我尝试做 Debug > Windows > Threads,但在 Debug 模式下问题不会发生,所以我找不到导致 UI 线程阻塞的原因。
这是什么原因造成的,我该如何解决?
更新
我尝试了以下方法,但它们不起作用:
我把它改成了
BeginInvoke。我添加了
DispatcherPriority.Send。
更新 2
public class UIHelper
{
public static void ShowTrayNotification(ToolTipIcon icon, string title, string text) {
NotifyIcon trayIcon = new NotifyIcon();
trayIcon.Icon = MyApp.Properties.Resources.myIcon;
trayIcon.Text = "MyApp";
trayIcon.BalloonTipClosed += TrayNotificationClosed;
trayIcon.Visible = true;
trayIcon.ShowBalloonTip(5000, title, text, icon);
}
static void TrayNotificationClosed(object sender, EventArgs e) {
((NotifyIcon)sender).Visible = false;
((NotifyIcon)sender).Icon = null;
((NotifyIcon)sender).Dispose();
sender = null;
}
}
【问题讨论】:
-
如何调用对象本身的调度程序?像
UIHelper.Dispatcher.Invoke...或者你可以尝试在调度程序之前放置一个MessageBox。Invoke 以查看该方法是否运行。这只是一个建议。 -
Dispatcher.Invoke() 当你的应用程序的 UI 线程被其他东西占用时会死锁。使用 Debug > WIndows > Threads 调试器窗口进行诊断。
-
@JakubLokša
dispatcher.Invoke永远不会运行。我使用MainWindow中的调度程序确保UIHelper中的NotifyIcon在主UI 线程中创建,否则它不会显示。 -
@HansPassant 使用
BeginInvoke会有什么不同吗?我可以尝试一下,但问题非常间歇性。 -
UIHelper.ShowTrayNotification会不会锁定UI线程?
标签: c# multithreading visual-studio-2013 static-methods notifyicon