In my WPF try to separate my classes logic from any interface related data and only supply ObservableCollection properties for binding.
Problem is, when I access those binded OCs from other threads, I am required to do so through the dispatcher. The result is that I am required to add many Dispatcher.Invoke() calls, hidden inside my classes, whenever one of the methods attempts to update the OCs.
How can I do that in a more clean and separated way, so the dispatcher calls be abstracted away from my methods?
I don't have a silver bullet. But if you are certain and ready to take the responsibility of implicit UI delegation, you can always inherit from ObservableCollection, override methods and dispatch all requests to UI.
But the following code makes me scary:
// somewhere in thread pool:
for(int i = 0; i < 1000; i++)
{
_dispatcherAwareCollection.Add(i);
}
It seems innocent, but under the hood it blocks calling thread 1000 times. Alternatives might be your specific BulkXXX() methods, that will delay notification until all elements are processed. This solution is not perfect either, since you wanted an abstraction that could let you seamlessly swap collections, but BulkXXX() methods are very specific to new collection.
Option 1
I think you should look into a better separation of your code using the MVVM pattern, if you aren't familiar with it, I highly suggest to see the following video as it explains exactly what you're looking for.
Specifically, however, in your case you should have the model class with regular collection (e.g List) on which you do all the work in the threads. Your ViewModel should contain the ObservableCollections and connect loosely with the collections that exist in the model, e.g, you can choose to subscribe via an event from your ViewModel to a certain update logic in your model. You will STILL need to use Dispatcher to update the OC, but you will only need to do it once.
Option 2
You can instead just use the solution described here. Basically, he created a new derived class from OC that allows you to dispatch changes from the code automatically without you ever needing to update the dispatcher yourself.
The common approach is to have a Dispatcher property on your view model (probably in a base class for all view models) that can be injected outside. It is OK to have it in a view model because view model SHOULD be aware of UI concepts, but it should not be aware of particular view (layout, controls, etc.) and certainly it should not have a reference to the view.
What you can do is you can make it easier to dispatch your code to the Dispatcher thread by creating a helper or a service that will abstract the dispatcher away. For example, you can create a helper like this:
public class AsyncHelper
{
public static void EnsureUIThread(Action action)
{
if (Application.Current != null && !Application.Current.Dispatcher.CheckAccess())
{
Application.Current.Dispatcher.BeginInvoke(action, DispatcherPriority.Background);
}
else
{
action();
}
}
}
And whenever you need to update you observable collection, you wrap you code in that helper method:
AsyncHelper.EnsureUIThread(() =>
{
// Update you observable collections here
});
OR, you can go further and use AOP (e.g. PostSharp) to specify declaratively (using attributes) that a method should be executed in the UI thread.
And finally, please note that you have to dispatch only collection updates to the UI thread. Usual properties can be safely updated from a background thread. The updates will be dispatched to the UI thread automatically by the binding mechanism. Probably in future versions of WPF updates to a collection from a background thread also will be supported.
Well you could write yourself an AsyncObservableCollection, if you know how to write it threadsafe. Then you can encapsulate the Dispatcher calls in it.
The problem is you would not use the standard ObservableCollection delivered within the .Net - Framework. It would increase the risk of errors in your application.
Another option would be to implement a WrapperClass, which contains and exposes an ObservableCollection for binding and has methods to modify the collection.
public class WrapperClass<T>
{
public ObservableCollection<T> Collection {get; set;}
public void Add(T item)
{
//do your dispatcher magic here
}
...
}
To modify the collection you implement the methods in it. The problem here is, that there is no guarantee, that others will use these methods, too.
I am afraid that you will have to wait for the next version of wpf
From this post:
A few nuggets we can expect to see in the next version of WPF include:
Hosting of Silverlight content with the new SilverlightHost element, without airspace issues (the inability to overlap WPF content over native Windows hWnd content)
Overall better management of airspace with hosted native hWnd-based content like the WebBrowser, HwndHost and WindowsFormsHost
Enabling binding and change notification for collections that are created on a background thread
Better integration with UI virtualization
Integration of the Ribbon control
And more
Use SynchronizationContext instead of Dispatcher. SynchronizationContext is common feature for threads synchronization in .NET, meanwhile Dispatcher is intentionally developed for WPF.
You probably want to use something like MTObservableCollection. I've used this in a project and it worked fantastically. Basically, it does all the dispatching work for you when the collection changed event is raised, by analysing the thread that the handler was assigned from, and dispatching accordingly.
The article is well worth a read, even if you don't plan to take this option.
I have an extension for this:
public static class DispatcherInvoker
{
public static void AddOnUI<T>(this ICollection<T> collection, T item)
{
Action<T> addMethod = collection.Add;
Application.Current.Dispatcher.BeginInvoke(addMethod, item);
}
}
EDIT:
I stole it from an stackoverflow post but forgot from which one
I think you have to much coupling if you need to think about threading in your model layer.
What you should do is to not connect your model directly to the GUI. As others have said, use a layer in between (MVVM).
This means that you let your MVVM layer respond to the change notifications from your observable collection. It is the MVVM layer that decides if and how these notifications should be passed on to the GUI. Look here for a way to lower the update frequency of the GUI to keep it usable.
In short:
Keep using an ObeservableCollection in your model layer if you like but don't use it directly in the GUI binding. Let another layer receive the notifications and control the GUI update.
Related
In a WPF application I'm working on I came across following code snippet;
public int SomeInteger
{
get { return _someInteger; }
set
{
_someInteger= value;
OnPropertyChanged("SomeInteger");
SomeIntegerChanged();
}
}
As you can see, inside the property setter a method is called. Is this approach correct or is there any better way to do in MVVM pattern WPF?
As above code snippet is a sample, actually the property setter might load a DataTable when the property changes which might be time consuming. I tried to make the application asynchronous using async and await but above scenarios causes problems since async and await doesn't have asynchronous property concept.
I also got across a way to bind a event to INotifyPropertyChanged and by checking which property triggers the event and call the method. But looking for any other alternatives.
Is this approach correct or is there any better way to do in MVVM pattern WPF?
This is, unfortunately, the common and accepted MVVM pattern across all of C#. I say "unfortunately" because this pattern does run into problems. It is based on events - which are problematic just on their own - and it also causes an immediate update, which in many cases is not desired.
For one example, sometimes it's desirable to have two properties that are mutually dependent - when the user changes one, the other one changes in relation to it - and this can cause problems since there's no way to distinguish "user changes" from "code changes".
For another example, sometimes you can end up with a whole tree of dependent properties, and it can take some time for all the changes to propagate through and stop interfering with each other.
More modern MVVM approaches like the atomically-updated single source of truth with single-directional data flow (as popularized by Redux) avoid the above problems. There is a C# Redux implementation; I don't know how easy it is to use. In my own CalculatedProperties library, I built my own "invalidation queue" to work around this, which defers all PropertyChanged updates until after the entire system's new steady-state is calculated.
I tried to make the application asynchronous using async and await but above scenarios causes problems since async and await doesn't have asynchronous property concept.
True. In particular, you can't "asynchronously get" a property. And this makes sense in the MVVM world; when WPF is updating the screen, and it asks your VM for a data value, then your VM can't say "hold on, I'll get it in a minute". WPF needs to know that value now so it can update the screen now.
Hooking up an asynchronous event handler is one way of kicking off asynchronous work when the value changes; that approach is fine. Usually, the presence of SomeIntegerChanged implies that there is a "changed" event specifically for that property, so hooking into PropertyChanged with string comparisons is probably the harder way to do it.
For more on asynchronous properties with MVVM, see my article on the subject.
In this case, calling the methods in the Setter is okay. Using INotifyPropertyChanged for property change notifications in WPF is the correct way, and adding the call to the Setter is the default way to implement it.
The call to SomeIntegerChanged(); depends a bit on what the method does (and if it's even required given you already implemented INotifyPropertyChanged).
Using properties as a consumer should have as little side-effects as possible, and generally should be simple operations. There's a nice guide on MSDN about that topic.
You should also avoid using strings of property names as parameters, in your case the call to OnPropertyChanged should look like this: OnPropertyChanged(nameof(SomeInteger));
A property setter shouldn't kick off a long-running operation. It should simply set the value of a backing field and perhaps call a fast synchronous method that returns just almost immediately. Please refer to #Stephen Cleary's blog post for more information.
If you need to call an asynchronous whenever SomeInteger gets set, you could for example hook up an async event handler for the PropertyChanged event, e.g.:
this.PropertyChanged += async (s, e) =>
{
if (e.PropertyName == nameof(SomeInteger))
{
await SomeAsyncMethod();
}
};
I would caution against premature optimisation.
Don't complicate your solution any more than is necessary.
If the change is immediate then there's no problem putting what you like in a setter.
Dependent property changes are an occasional requirement but also not usually a big deal.
If you have a long process needs to start then that sounds like it should be something discrete. You should initiate that processing on a separate thread and or decouple the processing. You could just start up a fire and forget thread ( not terribly elegant ).
You can decouple processing using service calls, message queues like msmq or RabbitMQ or pub sub. There are many pub sub approaches - a simple implementation being mvvmlight's messenger or prism's eventaggregator. More sophisticated would be NServiceBus or even Windows Workflow. If events are involved then weak events are preferable.
When a property changes its value I want to call an async method that fetches data from a web service an then updates another property to which the UI is bound causing the UI to update. It makes sense to me that the update is async as I want the UI to remain responsive while the update is going on.
Is it wrong to call an async method from the non async setter? I noticed that if the async method return void then VS does not complain but if it returns Task then visual studio complains that the call is not awaited. My code looks like this:
public int Property1
{
set
{
_property1 = value;
NotityPropertyChanged();
UpdateData();
}
}
private async void UpdateData()
{
// show data loading message
var data = await GetDataFromWebService();
Property2 = data;
// hide data loading message
}
It seems to work but I wonder if I am not using async the way it was intended given the warning I get from VS if the return type is Task.
UPDATE: Several answers and comments have suggest the user of commands rather than updating in response to a change in a property. For my case I am not sure how that could be applied so am providing more details about how the UI is expected to work.
In the user interface there is date picker (which is bound to the property in question on the view model) where the user selects the date for which he wants to view records. When a new date is selected by the user, the app should show a busy indicator, and then fetch records in the background to avoid blocking the UI thread. Preferably I want the update to be initiated when the date selected, without requiring the user to push a button after the date is selected.
Would it be better to bind the SelectionChanged event of the date picker to and async command on the ViewModel or alternatively have an sync handler for the SelectionChanged which calls the update method on the view model directly?
Is it wrong to call an async method from the non async setter?
In short, yes. Properties should not not be kicking off asynchronous background operations in their setters.
I recommend you to read Stephen Cleary's blog post and MSDN article on the subject:
Async Programming : Patterns for Asynchronous MVVM Applications: Data Binding: https://msdn.microsoft.com/en-us/magazine/dn605875.aspx
Async OOP 3: Properties: https://blog.stephencleary.com/2013/01/async-oop-3-properties.html
You may also want to look into a functional MVVM framework such as ReactiveUI that handles this scenario by converting properties into observable streams of values that you can subscribe to: https://reactiveui.net/docs/getting-started/
It's not the "cleanest" way as already stated, but you can leave it. It's not harmful in the first place except you are hiding an unexpected long and expensive operation behind a quick assignment.
MSDN says:
An async method can also have a void return type. This return type is used primarily to define event handlers, where a void return type is required. Async event handlers often serve as the starting point for async programs.
An async method that has a void return type can’t be awaited, and the
caller of a void-returning method can't catch any exceptions that the
method throws.
A simple solution could be to listen to the PropertyChanged event. This would be more like a work around to escape the setter. A better way is to make your ViewModel expose an update command by implementing the ICommand interface asynchrounous by adding asynchronous execution to it. You would then invoke this AsyncCommand from your View, whenever the property changes. You could also pass the new value as a command parameter to the ViewModel.
Automatically calling updates when just a property changes is usually a bad idea of itself.
Usually a button and a command are a better plan.
You could alternatively invoke a command from the UI rather than use that setter. And that'd be relatively simple to do.
At a minimum, you want a different thread for calling some web service in that sort of a way.
A fire and forget thread wouldn't exactly be terrible.
So long as you don't care so much what happens after you forgot it.
A common exception one can get when working with multiple threads in WPF is:
The calling thread cannot access this object because a different thread owns it
What are the options to deal with this properly?
Depending on the situation there are various options:
Accessing a control from another thread
e.g. updating a TextBlock with progress information.
Data Binding:
In this case the easiest thing you can do is avoiding the direct interaction with the control. You can just bind the property you want to access or modify to an object whose class implements INotifyPropertyChanged and then set the property on that object instead. The framework will handle the rest for you. (In general you rarely should need to interact with UI-elements directly, you can almost always bind the respective properties and work with the binding source instead; one case where direct control access may be necessary is control authoring.)
There are some cases where data binding alone is not enough, for example when trying to modify a bound ObservableCollection<T>, for this you need...
Dispatching:
You can dispatch your accessing code to the thread owning the object, this can be done by calling Invoke or BeginInvoke on the Dispatcher owning the object being accessed (getting this Dispatcher is possible on another thread).
e.g.
new Thread(ThisThreadStart).Start();
void ThisThreadStart()
{
textBlock.Dispatcher.Invoke(new Action(() => textBlock.Text = "Test"));
}
If it is not clear on which thread a method is executed you can use Dispatcher.CheckAccess to either dispatch or execute an action directly.
e.g.
void Update()
{
Action action = () => myTextBlock.Text = "Test";
var dispatcher = myTextBlock.Dispatcher;
if (dispatcher.CheckAccess())
action();
else
dispatcher.Invoke(action);
}
If an object is not a DispatcherObject and you still need the associated Dispatcher you can use Dispatcher.CurrentDispatcher in the thread creating the object (so doing this in the method being executed by a thread will not do you any good). For convenience as you usually create objects on the application's main UI thread; you can get that thread's Dispatcher from anywhere using Application.Current.Dispatcher.
Special cases:
BackgroundWorker
Move any control access to ProgressChanged as it occurs on the thread that created the instance (which should of course be the UI-thread)
Timers
In WPF you can use the DispatcherTimer for convenience, it does the dispatching for you so any code in Tick is invoked on the associated dispatcher. If you can delegate the dispatching to the data binding system you of course can use a normal timer as well.
You can read more about how the Dispatcher queue works and WPF threading in general on MSDN.
Accessing an object created on another thread
e.g. loading an image in the background.
If the object in question is not Freezable you should in general simply avoid creating it on another thread or restricting access to the creating thread. If it is Freezable you just need to call Freeze to make it accessible to other threads.
Accessing a data object from another thread
That is, the type whose instance is being updated is user-code. If an exception is thrown this situation probably came about by someone using DependencyObject as base type for a data class.
This situation is the same as accessing a control and the same approaches can be applied but usually it should be avoided in the first place. Granted, this allows for simple property change notifications via dependency properties and those properties can also be bound but often enough this is just not worth giving up thread-independency. You can get change notifications from INotifyPropertyChanged and the binding system in WPF is inherently asymmetrical, there always is a property that is bound (target) and something that is the source for this binding. Usually the UI is the target and the data is the source, meaning that only UI components should need dependency properties.
That would be several hundred lines of code, for something I "figured out".
But the summary is:
App_OnStartup
generate a background thread
in the callback,
Call
Application.Current.MainWindow.Dispatcher.CheckAccess() - gets the exception
Application.Current.Dispatcher.CheckAccess() does not
I have a udp listener object that communicates through events where the method/callbacks are +='ed in my mainWindow wpf .cs file.
The event handler functions are called with parameters, one being the message I want displayed in a listbox in the mainWindow.cs
Using the information in this thread by H.B. above;
I have added, tested and handled the crossthread in wpf in my eventhandler callback using the following code, but I use a real message not a hard coded one:
listBox1.Dispatcher.Invoke(new Action(() => listBox1.Items.Add("MessageHere")));
UPDATE:
This is better because you can put more things in the anonymous function.
listBox1.Dispatcher.Invoke((Action)delegate
{
listBox1.Items.Add(e.ReaderMessage);
});
I'm jusing Jurassic javascript compiler to run javascript in my C# application. Now, jurassic isn't thread-safe, and I call functions (in javascript) from threads all over the place, which I figured wasn't that smart. What I could do was ofcause just to create a simple lock on the javscript-engine, however, what I want is a programming model similar to the one you have when working with a GUI thread in WPF or WinForms. So, I spawned a thread, and created my javascript-engine inside that thread, and what I would like is that no other threads are allowed to edit the objects created in that thread (which will just be the javascript-engine and all the js-objectes). And then, to call js-code from other thread I'd like to use a dispatcher, or something similar, to make the js-thread run the code.
Is this possible in C#?
It doesn't quite answer your question but you may want to take a look at this MSDN article. It talks about the approach that WPF took with their objects and the Dispatcher model, as well as the Dispatcher, DispatcherObject and DispatcherSynchronizationContext classes.
What they recommend for individual objects is to inherit from DispatcherObject (which may not be feasible for your situation) and call the inherited VerifyAccess() method on public access.
public class ThreadOwnedObject : DispatcherObject
{
private string field;
public string ExposedProperty
{
get { return field; }
set
{
VerifyAccess();
field = value;
}
}
}
And the invocation would use the inbuilt Dispatcher.
ThreadOwnedObject ownedInstance = new ThreadOwnedObject();
ownedInstance.Dispatcher.Invoke(new Action(() => ownedInstance.ExposedProperty = "foo"));
Alternately, if that or the DispatcherSynchronizationContext in the article doesn't fit your needs, I imagine that you could probably create a mechanism that mimics the DispatcherObject by holding onto the Thread.CurrentThread.ManagedThreadId when an object is created and perform checks against that value for every exposed access. Beyond that or an equivalent, I don't think that there's a built-in mechanism that will associate a random object with a given thread.
I'm not quite sure what you are asking, but I'll try to help anyway.
Can you use a semaphore to lock the thread running the javascript engine? Even if you don't use the Semaphore class, you could use a boolean or "lock" keyword to protect the code block with the executing engine. The objects produced by that thread could be hidden by the class with the engine until you are ready. You could also expose a method in that class that would allow code injection or object fetching from behind the protected code.
I am converting a chat parser for a game i play that i wrote in c# winforms over to wpf, mainly just to get a better handle on MVVM and wpf. Here is a run down of how i have my project set up
View:
For now its just a simple ListBox with ItemSource bound to my viewmodels observable chat collection
Model:
I have multiple characters that can be logged in at one time and each character has a chat class. The chat class starts a background worker that grabs and next line of chat from the game and fires off an event called IncomingChat with this line.
public event Action<Game.ChatLine> IncomingChat;
I'm using a background worker to fire an event in my backgroundworkers progresschaged event because when i was using a timer i kept getting a threading issue. At first i corrected this by changing my Timer to a DispatchTimer, but this didn't seem right to me to have a DispatchTimer in my model.
ViewModel:
Since i have multiple characters i am creating multiple ChatViewModels. I pass a character into the ChatViewModels constructor and subscribe to the Chat event. I create a ObservableColleciton to hold my chat lines when this event is received. Now I'm receiving a threading issue on my viewModel when trying to add the line i receive from my chat event to my observablecollection.
I got around this by making my viewmodels incoming chat event handler look like so
public ObservableCollection<Game.ChatLine) Chat {get; private set;}
void Chat_Incoming(Game.ChatLine line)
{
App.Current.Dispatcher.Invoke(new Action(delegate
{
Chat.Add(line)
}), null);
}
This doesn't feel right to me though. Although it works, using Dispatcher in my viewmodel like this seems out of place to me.
Although it works, using Dispatcher in my viewmodel like this seems out of place to me.
This isn't a completely unreasonable approach, and is the approach that many people take. Personally, if you're using WPF (or Silverlight 5), and have access to the TPL, I prefer to use the TPL to handle this.
Assuming your ViewModel is constructed on the UI thread (ie: by the View, or in response to a View related event), which is the case nearly always IMO, you can add this to your constructor:
// Add to class:
TaskFactory uiFactory;
public MyViewModel()
{
// Construct a TaskFactory that uses the UI thread's context
uiFactory = new TaskFactory(TaskScheduler.FromCurrentSynchronizationContext());
}
Then, when you get your event, you can use this to marshal it:
void Chat_Incoming(Game.ChatLine line)
{
uiFactory.StartNew( () => Chat.Add(line) );
}
Note that this is slightly different than your original, since it's no longer blocking (this is more like using BeginInvoke instead of Invoke). If you need this to block until the UI finishes processing the message, you can use:
void Chat_Incoming(Game.ChatLine line)
{
uiFactory.StartNew( () => Chat.Add(line) ).Wait();
}
A View Model is a good place to do a Thread Synchronization. Remove the DispatcherTimer from your model and let the VM handle it.
I love Reed's answer, and agree with your concerns that something isn't right with your use of the Dispatcher. Your VM references App, which is, in my mind, a reference to a UI artifact (or control). Use Application instead or, better yet, inject the correct Dispatcher instance into your VM, which avoids the need to instantiate your VM in the UI thread.