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?
source to share
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
.
source to share
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();
source to share
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));
source to share