
这是可行的,因为DispatcherTimer是Dispatcher的一部分,但是冻结了UI:
DispatcherTimer dispTimer = new DispatcherTimer();
dispTimer.Tick += dispTimer_Tick;
dispTimer.Interval = new TimeSpan(0, 0, 45);
dispTimer.Start();
private void dispTimer_Tick(object sender, EventArgs e)
{
PartialEmployees.Clear();
}
因此,使用BackgroundWorker我将其拼凑而成:
DispatcherTimer dispTimer = new DispatcherTimer();
dispTimer.Tick += dispTimer_Tick;
dispTimer.Interval = new TimeSpan(0, 0, 45);
dispTimer.Start();
private void dispTimer_Tick(object sender, EventArgs e)
{
BackgroundWorker _worker = new BackgroundWorker();
_worker.DoWork += DoWork;
_worker.RunWorkerAsync();
}
private void DoWork(object sender, DoWorkEventArgs e)
{
Dispatcher.CurrentDispatcher.BeginInvoke( new Action(()=>
{
PartialEmployees.Clear();
}));
}
但是,UI没有任何反应.我缺少什么/做错了什么?
>从后台线程使用Dispatcher.CurrentDispatcher时,它将获取后台线程的Dispatcher,而不是UI线程的Dispatcher.
>从您的描述中,我发现您的PartialEmployees.Clear()方法需要花费大量时间来执行,并且您希望避免在执行期间锁定UI线程.但是,让BackgroundWorker在UI线程上调用PartialEmployees.Clear()将具有与使用DispatcherTimer相同的效果,因此您需要的解决方案与您要使用的解决方案不同.
如果只想解决Dispatcher.CurrentDispatcher问题,只需将当前Dispatcher存储在这样的局部变量中:
private void dispTimer_Tick(object sender, EventArgs e)
{
var uiDispatcher = Dispatcher.CurrentDispatcher;
BackgroundWorker _worker = new BackgroundWorker();
_worker.DoWork += (sender, e) =>
uiDispatcher.BeginInvoke(new Action(() =>
{
PartialEmployees.Clear();
}));
_worker.RunWorkerAsync();
}
这将使您的UI更改生效,但仍将在更改期间锁定UI,就像您没有使用BackgroundWorker一样.原因是:
> DispatcherTimer触发,在UI线程上执行.它所做的全部(dispTimer_Tick)是启动BackgroundWorker,然后退出.
> BackgroundWorker自己执行therad.它所做的只是调度Dispatcher回调,然后退出.
> Dispatcher回调再次在UI线程上执行.它调用PartialEmployees.Clear()会花费一些时间,并在执行时锁定UI线程.
因此,您的行为与DispatcherTimer回调直接调用PartialEmployees.Clear()相同:在每种情况下,耗时的操作都在UI线程上执行.
锁定的原因是,每当您在UI线程上进行大量工作时,都会在运行时得到瞬时锁定.解决方案是将您的工作分成较小的部分,然后一次从DispatcherTimer或BackgroundWorker中一次完成.在您的情况下,检查PartialEmployees.Clear()的代码以查看是否可以增量执行.
转载注明原文:带有Dispatcher的BackgroundWorker似乎什么也没做 - 乐贴网