【发布时间】:2016-09-27 17:29:37
【问题描述】:
我有一个矩形,我想让它可见,然后我想等待 500 毫秒,然后我想让它再次不可见。
最初我尝试了这段代码:
MuzzleFlash.Visibility = Visibility.Visible;
Thread.Sleep(500);
this.UpdateLayout();
this.InvalidateVisual();
MuzzleFlash.Visibility = Visibility.Collapsed;
我尝试了这两条中间线,因为它们据说会强制更新窗口,但所做的只是暂停半秒钟,而没有更改任何类型的矩形。
所以我听说了 BackgroundWorkers 以及我应该如何使用它们。经过一些简短的阅读,我想出了这个。请注意,Shoot 订阅了 Canvas 上的 MouseDown 事件,该事件以前有效:
private void Shoot(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
BackgroundWorker UIUpdater = new BackgroundWorker();
UIUpdater.WorkerSupportsCancellation = true;
UIUpdater.WorkerReportsProgress = false;
UIUpdater.DoWork += new DoWorkEventHandler(UI_DoWork);
UIUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(cancelUIUpdate);
}
private void UI_DoWork(object sender, DoWorkEventArgs e)
{
MuzzleFlash.Visibility = Visibility.Visible;
Thread.Sleep(500);
this.UpdateLayout();
this.InvalidateVisual();
MuzzleFlash.Visibility = Visibility.Collapsed;
}
private void cancelUIUpdate(object sender, RunWorkerCompletedEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
bw.CancelAsync();
}
现在它甚至没有暂停半秒钟,向我表明工人没有做任何事情。我该如何解决这个问题,并使矩形出现/消失?
【问题讨论】:
-
我会使用计时器。你并没有真正在工作。
-
它不起作用,因为你在工作线程中做所有事情。主 UI 线程说 “启动一个后台工作程序,然后结束”,而 bg 工作人员说 “设置可见标志为真,等待一段时间,设置可见标志为假,然后结束回到 UI 线程,所以UI 可以更新”。请注意,bg 线程从不将通知发送回主 UI 线程以更新显示。如果您想这样做,我建议您查看 WPF 的 Dispatcher。请参阅 this answer 以获取简短摘要,该摘要使用与您在此处要执行的操作类似的示例。
-
一个简单的“解决方案”是将您的
MuzzleFlash.Visibility = Visibility.Visible行移动到您的主 UI 线程,以便从Shoot(...)方法中执行。然后代码说“设置可见标志为真,启动一个bg工作人员,然后结束并更新显示”,而bg工作人员说“等待一段时间,设置可见标志为假,然后结束返回UI线程,以便它可以更新”。此外,您可能希望将 "set visible flag false" 位放在 RunWorkerCompleted 中,因为 WPF 通常不会更新未在其上创建的线程上的对象,因此您可能会在尝试时遇到异常从 bg 工作人员更新。 -
@Rachel 谢谢你,我让它以这种方式工作。不过,也许在 XAML 中使用动画可能会更好?我不太了解 SE 礼仪,所以不确定我应该选择哪个答案
-
您可以接受您认为最适合您的任何一个 :) 就我个人而言,我认为 Himansh's answer 是最接近我的评论并维护您当前代码的东西,但是它缺乏任何解释真的不是我们希望在答案中看到的。我更喜欢LoopedCode's answer,尽管它没有回答您关于后台工作人员使用情况的具体问题。有时,替代建议是比对所提出的确切问题的答案更好的解决方案。 :)
标签: c# wpf multithreading user-interface backgroundworker