Dispatcher.BeginInvoke always returns DispatcherOperationStatus.Pending status

I am trying to update ObservableCollection

asynchronously using the following code in my WPF project:

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

      

But unfortunetly status alway is equal DispatcherOperationStatus.Pending

.

ps: Maybe my problem is that I am using ElementHost in a WinForms project?

+3


source to share


4 answers


If you want something to run after the asynchronous operation has completed, you must use this event Completed

.

See this answer for an example



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

      

There's a chance the operation will complete before subscribing, so you can also check the Status property for completion after:

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

      

As for the real problem, I'm not sure without being able to reproduce it. If I had to wary of guessing, it would be that your loop is binding the current thread Dispatcher

, so it cannot handle the operation BeginInvoke

you told it to, so it will always sit in Pending

.

+12


source


The state of your operation seems to be outdated because an enum is a value type and you are storing it in a variable. Changing the code on this should fix your problem:

    var op = Dispatcher.BeginInvoke(new Action(() => { ChangeCollectionByAction(action); }), null);
    while (op.Status!= DispatcherOperationStatus.Completed)
    {
        status = op.Wait(TimeSpan.FromSeconds(1));
    }

      



In fact, you can replace all of your code with just this single line:

Dispatcher.BeginInvoke(new Action(() => ChangeCollectionByAction(action))).Wait();

      

+4


source


Dispatcher.BeginInvoke()

do not expect.

If .NET 4.5 is available for you, you can use Dispatcher.InvokeAsync()

:

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

      

+1


source


Can you check the value Dispatcher.Thread.ThreadState

before calling BeginInvoke

?

I think the problem is that the Dispatcher thread has stopped. Therefore, calling Dispatcher.BeginInvoke

on a stopped thread will cause an infinite wait status as it cannot start anything.

0


source







All Articles