在WPF表单上,当程序执行一些冗长的任务时,我需要在文本字段中显示两条状态消息:“已启动”和“已完成”,以保持简单。消息显示在绑定到属性的文本块中,当然,在设置器中使用OnPropertyChange。
问题:当我更改此属性时,只显示第二条消息。
StatusMessage = "Started";
Thread.Sleep(700); // Searching the harddrives and make some lists in the real prog.
StatusMessage = "Finished";对我来说很奇怪:如果我在第一次属性更改和Sleep之间放置一个MessageBox.Show -这当然没有意义-一切都很好:
StatusMessage "Started";
MessageBox.Show("Just click");
Thread.Sleep(700);
StatusMessage "Finished";尝试在消息窗口中实现同样的操作会显示出几乎相同的行为:新窗口将打开,但不会充满内容-除非在代码中放入无意义的MessageBox.Show。(我猜这有相同的根本原因,所以在这里的线程中添加这个。)
MsgWindow mw = new MsgWindow();
mw.Show();
MessageBox.Show("Just click"); //If I delete this line the window opens without content, color etc.
Thread.Sleep(700);
mw.Close();我的错误在哪里?
发布于 2019-09-22 23:26:53
在您的示例中,问题是调用Thread.Sleep -根据msdn,这将执行以下操作:
将当前线程挂起指定的时间量。
当前线程是UI线程,它需要是空闲的,绑定引擎才能更新和显示Started文本。然而,在调用OnPropertyChanged之后,UI线程立即挂起-只有在您将文本更改为Finished之后,UI线程才会变得空闲。
这在现实生活中也是一样的--您的工作是在UI线程上同步完成的,因此UI线程不能自由地更新UI。
在这里,async/await是您的朋友--下面的示例代码应该可以像您期望的那样工作
StatusMessage = "Started";
await Task.Delay(700);
StatusMessage = "Finished";在实际案例中,理想情况下,您应该能够以async方式对长期运行的流程进行建模,例如
StatusMessage = "Started";
await DoSomeAsyncWork();
StatusMessage = "Finished";或者,如果您的工作必须是同步的,则可以将其包装在Task中,如下所示:
StatusMessage = "Started";
await Task.Run(() => DoSomeWork());
StatusMessage = "Finished";我推荐这篇关于如何正确使用async的Best Practices in Asynchronous Programming msdn杂志文章。
https://stackoverflow.com/questions/58049937
复制相似问题