我有一个FileSystemWatcher可以对Changed事件做出反应。
我想打开文件,阅读其内容,将其显示在文本框中,并隐藏1秒后创建的弹出窗口。代码几乎可以工作但隐藏弹出窗口时会出现问题。
以下是代码片段:
txtLog.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() {
this.txtLog.Text = dataToDisplay;
extendedNotifyIcon_OnShowWindow();
Thread threadToClosePopup = new Thread(new ThreadStart((Action)delegate() {
Thread.Sleep(1000);
extendedNotifyIcon_OnHideWindow();
}));
threadToClosePopup.Start();
});
如您所见,我使用Invoke来设置文本,因为事件位于不同的线程(FileSystemWatcher)中。但是为了隐藏窗口,extendedNotifyIcon_OnHideWindow()不会在GUI的线程中执行。如何在GUI线程中执行它?
答案 0 :(得分:17)
适用于margin
的{{1}}。
WPF
这将不一致地工作(如果我们在Reactive Extensions的处理程序中,它将会失败):
MVVM
按照设计,任何线程都可以有一个与之配对的调度程序线程,请参阅MSDN: Dispatcher Class。
如果我们从任何线程引用Application.Current.Dispatcher.Invoke(
() =>
{
// Code to run on the GUI thread.
});
,它实际上会创建一个新的调度程序线程,该线程与官方WPF UI调度程序线程分开。当我们尝试在这个新创建的调度程序线程上执行代码时,WPF将抛出,因为它不是官方的UI调度程序线程。
解决方案是始终使用Dispatcher.CurrentDispatcher.Invoke(
() =>
{
// Fails if we are inside a handler for Reactive Extensions!
});
或Dispatcher.CurrentDispatcher
。请参阅What's the difference between Invoke() and BeginInvoke()。
经过测试:
Application.Current.Dispatcher.Invoke()
Application.Current.Dispatcher.BeginInvoke()
WPF
.NET 4.5
答案 1 :(得分:10)
要在GUI线程上执行extendedNotifyIcon_OnHideWindow
方法,请像使用Dispatcher
一样显示它。
Thread threadToClosePopup = new Thread(new ThreadStart((Action)delegate() {
Thread.Sleep(1000);
txtLog.Dispatcher.Invoke(
DispatcherPriority.Normal,
(Action)() => extendedNotifyIcon_OnHideWindow());
}));
答案 2 :(得分:2)
这将为您提供Window调度程序:
Dispatcher.CurrentDispatcher
只要你在windows线程上获得它。
答案 3 :(得分:2)
使用Control.Invoke
txtLog.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)delegate() {
this.txtLog.Text = dataToDisplay;
extendedNotifyIcon_OnShowWindow();
Thread threadToClosePopup = new Thread(new ThreadStart((Action)delegate() {
Thread.Sleep(1000);
extendedNotifyIcon.Invoke(extendedNotifyIcon_OnHideWindow);
}));
threadToClosePopup.Start();
});
答案 4 :(得分:1)
将extendedNotifyIcon_OnHideWindow();
包裹到Dispatcher.Invoke()
但是我宁愿使用动画和使用TimeLrigger来触发TimeLine.Completed事件来进行(所有im XAML)。
答案 5 :(得分:0)
问题是extendedNotifyIcon_OnHideWindow
正在UI线程以外的线程上执行。您还需要使用Dispatcher
作为该部分。另外,我不会创建专用线程只是等待一秒钟。您可以轻松地将该部分重构为System.Threading.Timer
。这是我的重构版本。
txtLog.Dispatcher.Invoke(
(Action)(() =>
{
txtLog.Text = dataToDisplay;
extendedNotifyIcon_OnShowWindow();
new Timer(
(state) =>
{
button1.Dispatcher.BeginInvoke(
(Action)(() =>
{
extendedNotifyIcon_OnHideWindow();
}), null);
}, null, 1000, Timeout.Infinite);
}));