C# 如何在wpf中按顺序从子窗口更新父UI窗口的标签控件?
我试图找出答案,但没有找到真正的答案。有人能回答以下问题吗?我试图通过调用Dispatcher方法来更新父窗口中的状态,但我看到它没有按顺序更新状态。我在主窗口中看到状态更新,如下所示: 第一个进程已启动。。。 第一道工序完成了! 第三道工序完成了 除了UpdateStatus之间的延迟之外,还可以使用其他方法或任务。那么,为什么它不更新其他状态呢?有真实的答案吗C# 如何在wpf中按顺序从子窗口更新父UI窗口的标签控件?,c#,wpf,dispatcher,C#,Wpf,Dispatcher,我试图找出答案,但没有找到真正的答案。有人能回答以下问题吗?我试图通过调用Dispatcher方法来更新父窗口中的状态,但我看到它没有按顺序更新状态。我在主窗口中看到状态更新,如下所示: 第一个进程已启动。。。 第一道工序完成了! 第三道工序完成了 除了UpdateStatus之间的延迟之外,还可以使用其他方法或任务。那么,为什么它不更新其他状态呢?有真实的答案吗 private void Button_Click(object sender, RoutedEventArgs e)
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;
}
));
}
单个线程不能同时更新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;
}
您正在UI线程中同步运行所有内容,在完成之前阻止任何调用(因此不进行更新,然后一次执行所有更新)。只需在任务中移动代码:
void Button_Click(object sender, RoutedEventArgs e) => Task.Run(() =>
{
... // rest of your code
});
你们应该很好(除非你们按两次按钮,但我想这很容易解决)
顺便说一句,您还可以使用另一个invoke重载:
Dispatcher.Invoke(() => lblTest.Content = message);
我希望这将使情况更加清楚
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!");
}
谢谢你的评论。但是,如果有任何方法可以代替延迟,那么它将如何工作呢?那么您需要在后台线程上实际执行一些长时间运行的工作。否则,“第三个过程完成!”状态确实会立即显示。如果该方法需要1或2分钟,则可以轻松查看状态更改。我如何才能阻止那个时间,使状态不能立即更新?但我不知道我的方法将运行多长时间。若我给任务延迟50秒,方法运行110秒,那个么它可能不起作用。我猜。你在说什么方法?你在最初的问题中没有提到任何问题。如前所述,如果你有其他问题,请问一个新问题。如果您确实想使用sleep,那么@mm8(
async/await
)的解决方案会更好,尽管在这种情况下我只会使用计时器和消息集合。我已经考虑了同步方法,再次考虑了异步方法-使用async/await
方法。