I'm working on a WPF app and I simply want to alter the cursor before and after the task runs. I have this code:
this.Cursor = Cursors.Wait;
Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds)).ContinueWith(_ => this.Cursor = Cursors.Arrow);
The cursor indeed changes to the wait cursor, but it doesn't change back to the arrow when the task is done. If I put a breakpoint in the ContinueWith() method, it gets hit. But the cursor doesn't change back to an arrow. Why?
This was the old way I was trying it. The cursor changed back to an arrow, but I don't want to Wait() for the task.
this.Cursor = Cursors.Wait;
Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds)).Wait();
this.Cursor = Cursors.Arrow;
The cursor change needs to be done on the UI thread. You can either use the the overload of ContinueWith that takes a task scheduler:
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory
.StartNew(() => PerformMigration(legacyTrackerIds))
.ContinueWith(_ => this.Cursor = Cursors.Arrow, uiScheduler);
Or use the Dispatcher.Invoke method:
Task.Factory
.StartNew(() => PerformMigration(legacyTrackerIds))
.ContinueWith(_ => { Dispatcher.Invoke(() => { this.Cursor = Cursors.Arrow; }); });
I think you need to use the correct synchronization context:
this.Cursor = Cursors.Wait;
var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext());
Task.Factory.StartNew(() => PerformMigration(legacyTrackerIds))
.ContinueWith(_ => this.Cursor = Cursors.Arrow, uiScheduler);
The problem is that the continuation needs to run in the UI thread. Currently it's being done in a background thread.
Add TaskScheduler.FromCurrentSynchronizationContext()
to the second parameter of ContinueWith
to have it run in the UI thread.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With