I've had several problems with the ownership of wpf-objects when a task in the domain-level sets a property which the gui subscribes to, and the gui then tries to redraw some metainformation in an overlay canvas. I've solved several situations by using TPL's ContinueWith-mechanism where the new task is run on the GUI-thread.
After working on a problem today, where images are fetched every time the user changes the selected row in a table, I started thinking if there is a better way to do this. If I could only get all notifications to run on the GUI-thread, without having to use TPL's ContinueWith...
So I've now created a small test-project that has some classes, a window showing info, and some extension methods that run all the notifications on the GUI-thread.
This is the essence of the extension methods:
public static TaskScheduler GuiContext;The GuiContext field needs to be set on startup from the MainWindow, e.g. in the Loaded-event. It appears as though the extension-methods works like a charm.
public static void Notify(this PropertyChangedEventHandler self, INotifyPropertyChanged sender, string propertyName) {
if (self == null) return;
Task.Factory.StartNew(() => self(sender, new PropertyChangedEventArgs(propertyName)), CancellationToken.None, TaskCreationOptions.None, GuiContext);
}
I made the test-app start several threads that updates the objects in the controller several times, and as long as I allow the gui some cpu-time(put in some small sleeps in the threads), the gui is responsive and it updates the textboxes with values from the different threads.
I'm aware that just updating the same values from several threads is not a good idea, but for showing data in the gui I'm really just interested in showing the latest values, and I have control over cancellelation on the background tasks in the real application. So for the purpose of the test-app I don't think this is important.
I'm writing this post in the hopes that someone will take a poke at my project and tell me if they find any flaws or large weaknesses that I've overlooked. Here is a link to the project file.