Dispatcher.BeginInvoke始终返回DispatcherOperationStatus.Pending状
本文关键字:DispatcherOperationStatus Pending 返回 BeginInvoke Dispatcher | 更新日期: 2023-09-27 18:29:00
我尝试在WPF项目中使用以下代码异步更新ObservableCollection
:
if (Dispatcher.Thread != Thread.CurrentThread)
{
if (Dispatcher.Thread.ThreadState != ThreadState.Stopped && !Dispatcher.Thread.IsBackground)
{
Dispatcher.Invoke(new Action(() => { ChangeCollectionByAction(action); }), null);
}
else
{
var op = Dispatcher.BeginInvoke(new Action(() => { ChangeCollectionByAction(action); }), null);
var status = op.Status;
while (status != DispatcherOperationStatus.Completed)
{
status = op.Wait(TimeSpan.FromSeconds(1));
}
}
}
但不协调状态总是等于DispatcherOperationStatus.Pending
。
p.s.:我在WinForms项目中使用ElementHost可能是我的问题吗?
如果您希望在异步操作完成后运行某个东西,则应该使用它的Completed
事件。
有关的示例,请参见此答案
var dispatcherOp = Dispatcher.BeginInvoke( /* your method here */); dispatcherOp.Completed += (s, e) => { /* callback code here */ };
操作有可能在您订阅之前完成,因此您也可以在以下时间之后测试Status属性以完成:
if (dispatcherOp.Status == DispatcherOperationStatus.Completed) { ... }
至于实际的问题,如果不能重现的话,我不确定。如果非要我冒险猜测的话,可能是你的循环占用了当前的Dispatcher
线程,所以它无法处理你让它处理的BeginInvoke
操作,所以它总是位于Pending
。
操作的状态似乎是过时的,因为enum是一种值类型,并且您将其存储在一个变量中。将你的代码更改为这个应该可以解决你的问题:
var op = Dispatcher.BeginInvoke(new Action(() => { ChangeCollectionByAction(action); }), null);
while (op.Status!= DispatcherOperationStatus.Completed)
{
status = op.Wait(TimeSpan.FromSeconds(1));
}
事实上,你可以用这一行来替换所有的代码:
Dispatcher.BeginInvoke(new Action(() => ChangeCollectionByAction(action))).Wait();
Dispatcher.BeginInvoke()
不可用。
如果.NET 4.5对您可用,那么您可以使用Dispatcher.InvokeAsync()
:
if (Dispatcher.Thread != Thread.CurrentThread)
await Dispatcher.InvokeAsync(() => ChangeCollectionByAction(action));
在调用BeginInvoke
之前,是否可以检查Dispatcher.Thread.ThreadState
值?
我认为Dispatcher线程的问题是已停止。因此,在停止的线程中调用Dispatcher.BeginInvoke
将导致无穷大的挂起状态,因为它不能运行任何东西。