Dispatcher.BeginInvoke始终返回DispatcherOperationStatus.Pending状态

时间:2012-03-26 17:39:34

标签: c# wpf multithreading mvvm

我尝试使用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的问题?

4 个答案:

答案 0 :(得分:13)

如果您希望在异步操作完成后运行某些内容,则应使用它的Completed事件。

请参阅this答案以获取示例

var dispatcherOp = Dispatcher.BeginInvoke( /* your method here */);
dispatcherOp.Completed += (s, e) => { /* callback code here */ };
     

在您订阅之前,操作有可能完成,所以   你也可以测试Status属性是否完成:

if (dispatcherOp.Status == DispatcherOperationStatus.Completed) { ... }

至于实际问题,我不确定无法重现它。如果我不得不冒险猜测,那就是你的循环会占用当前的Dispatcher线程,因此它无法处理你告诉它处理的BeginInvoke操作,所以它总会坐着在Pending

答案 1 :(得分:4)

您的操作状态似乎已过时,因为枚举是一种值类型,您将其存储在变量中。 将代码更改为此可以解决您的问题:

    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();

答案 2 :(得分:1)

Dispatcher.BeginInvoke()无法等待。

如果您可以使用.NET 4.5,则可以使用Dispatcher.InvokeAsync()

if (Dispatcher.Thread != Thread.CurrentThread)
    await Dispatcher.InvokeAsync(() => ChangeCollectionByAction(action));

答案 3 :(得分:0)

您可以在致电Dispatcher.Thread.ThreadState之前检查BeginInvoke值吗?

我认为Dispatcher线程已停止的问题。因此,在已停止的线程中调用Dispatcher.BeginInvoke将导致无限等待状态,因为它无法运行任何内容。