我试图找出答案,但没有找到真正的答案。谁能回答以下问题?我试图通过调用Dispatcher方法更新父窗口中的状态,但我发现它不会以顺序方式更新状态。我在主窗口中看到状态更新如下:
第一道工序开始...... 第一个过程完成! 完成第三个过程!
可以有一些其他方法或任务,而不是UpdateStatus之间的延迟。那么,为什么它不更新其他状态?有什么真正的答案吗?
private void Button_Click(object sender, RoutedEventArgs e)
{
UpdateStatus("First Process started...");
Thread.Sleep(5000); //or any method
UpdateStatus("First Process done!");
Thread.Sleep(5000); //or any method
UpdateStatus("Second Process started...");
Thread.Sleep(5000); //or any method
UpdateStatus("Second Process done!");
Thread.Sleep(5000); //or any method
UpdateStatus("Third Process started...");
Thread.Sleep(5000); //or any method
UpdateStatus("Third Process done!");
}
private void UpdateStatus(string message)
{
Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new ThreadStart(delegate
{
MainWindow.main.lblTest.Content = message;
}
));
}
答案 0 :(得分:0)
单个线程无法同时更新UI和睡眠。
您可以在状态更新之间异步等待:
private async void Button_Click(object sender, RoutedEventArgs e)
{
UpdateStatus("First Process started...");
await Task.Delay(5000);
UpdateStatus("First Process done!");
await Task.Delay(5000);
UpdateStatus("Second Process started...");
await Task.Delay(5000);
UpdateStatus("Second Process done!");
await Task.Delay(5000);
UpdateStatus("Third Process started...");
await Task.Delay(5000);
UpdateStatus("Third Process done!");
}
private void UpdateStatus(string message)
{
MainWindow.main.lblTest.Content = message;
}
答案 1 :(得分:0)
我希望这会更清楚。
private async void Button_Click(object sender, RoutedEventArgs e)
{
// I run on the main thread and return immediately
await SearchForAliensAsync();
}
private async Task SearchForAliensAsync()
{
// I run on (capture) the caller thread (main thread)
UpdateStatus("Searching for aliens...");
/* Dispatch the dirty work on a background thread and return immediately,
* so that the caller thread (main thread) remains responsive.
* If you don't do that, the main thread will get blocked.
* From the user perspective the UI is frozen.
* The main thread will search infinitely for aliens,
* instead of doing its main job - poping and dispatching messages from
* its message queue (Win32 is event driven).
* The operating system will keep notifying the main thread,
* that the user has clicked on the window or smashed multiple keys on the keyboard,
* but the main thread won't listen, it's searching for aliens!
* The operating system monitors all main threads, by measuring what
* time has elapsed from the last call to GetMessage(...) and
* if the latter exceeds a certain amount, it will play a trick on you.
* The OS will create a transparent window and place it on top of the
* unresponsive one, so that it can detect the next angry mouse click
* and display the famous "Application is not responding" dialog...
*/
await Task.Run(() =>
{
// I run synchronously on the thread pool and I won't finish any time soon..
SearchForAliens();
});
// When my time comes, I'll be dispatched on the captured thread (main thread)
UpdateStatus("Aliens exist!");
}
答案 2 :(得分:-1)
您正在UI线程中同步运行所有内容,阻止任何调用,直到您完成(因此没有更新,然后一次更新所有更新)。只需在任务中移动代码:
void Button_Click(object sender, RoutedEventArgs e) => Task.Run(() =>
{
... // rest of your code
});
你应该没问题(除非你按两次按钮,否则这很好,但我想这很容易解决)。
顺便说一句,您还可以使用另一个调用重载:
Dispatcher.Invoke(() => lblTest.Content = message);