Thread safe, Silverlight - silverlight

I use very often RIA WCF Services and I inject the same context in several ViewModel. My problem is that as you know, the context of RIA Services, is not thread safe.
So I my solution "home made" for synchronization. I use backgrounds workers, and using PostSharp, I apply my attribute
[UniqueThread ("Data")] on the method and voila.
Do I complicate things? Are there simpler solutions?
Best regards,Vincent BOUZON

In our case we added an OnUiThread method to our BaseViewModel (which also supplies INotifypropertyChanged handler and some other handy util methods).
Whenever we need to ensure an operation is done on the UI thread we call OnUiThread with a lambda expression (or a callback) to do the work.
protected delegate void OnUiThreadDelegate();
protected void OnUiThread(OnUiThreadDelegate onUiThreadDelegate)
{
if (Deployment.Current.Dispatcher.CheckAccess())
{
onUiThreadDelegate();
}
else
{
Deployment.Current.Dispatcher.BeginInvoke(onUiThreadDelegate);
}
}
An example of a call might look like:
this.OnUiThread(() =>
{
this.ViewModelList = resultList;
});

That certainly seems excessively complicated, unless you've already done a lot of other work to force your viewmodels to be running on separate threads. By default, of course, anything you write is going to be running on the main foreground thread, and there shouldn't be any need to engage in the sort of complicated stuff you're describing. Or are your view models actually running on separate (background) threads?

Related

How to understand "UI Thread" coverage from source code in WP

I wonder whether it is possible to understand which code pieces are executed on UI from source code just depending on static analysis in Windows Phone development.
I try to implement a static analysis finding places in which Dispatcher.(Begin)Invoke is used unnecessarily.
These are the places that UI thread definitely executes:
event handlers which gets "RoutedEventArgs" as a parameter
Constructors of UI elements
the definitions of method calls in above methods (means that transitively looking at call graphs of these event handler methods and UI constructors)
Is there any other place or is there something wrong about above list?
Every method called by using the Dispatcher or the right SynchronizationContext will execute on the UI thread. That makes exhaustive static analysis impossible. For instance, the callback of the WebClient class executes on the UI thread. How are you supposed to predict those corner cases?
A quick tip though, quite useful is you have a method that can be called both from a UI or a non-UI thread. By calling the method Dispatcher.CheckAccess() (this method isn't shown by the intellisense in Visual Studio, so it's hard to discover), you can know if you need to call the Dispatcher or not:
if (Dispatcher.CheckAccess())
{
// In the UI thread
SomeMethod();
}
else
{
// Not in the UI thread
Dispatcher.BeginInvoke(SomeMethod);
}
From there, you can write a wrapper:
public void CallDispatcherIfNeeded(Action method) // You might want a shorter name
{
if (Dispatcher.CheckAccess())
{
// In the UI thread
method();
}
else
{
// Not in the UI thread
Dispatcher.BeginInvoke(method);
}
}
And then you just have to call it, without worrying whether you're on the UI thread or not:
CallDispatcherIfNeeded(SomeMethod);
That said, if your code is correctly written, it's quite rare to need this kind of trick.
I would look at when Dispatcher.BeginInvoke is actually needed, not the other way around.
It is almost never needed, excepted when handing an async completed event which may start out on a background thread, and thus if you want to do something with the UI, you need to marshal it over to the UI thread.
In other words, unless you need to do something with the UI from a background thread, you don't need it.
Greg

Silverlight hangs on Prism's EventAggregator Subscribe method

I am using Prism's event aggregator in Silverlight and am having a hard time with Subscribe. When the code hits the Subscribe method it just hangs and never makes it to the next line of code. If I break up the code, _eventAggregator.GetEvent() seems to return a valid instance of the event. The code definitely hangs on "Subscribe". What could I be doing wrong here? The JobCompletedEvent is declared in another library (which is a dependency for this library).
public void CallMeWhenTheJobIsDone(Action callback)
{
if (_jobIsRunning)
_eventAggregator.GetEvent<JobCompletedEvent>().Subscribe((e) => callback(), ThreadOption.UIThread);
else
callback();
}
public class JobCompletedEvent: Microsoft.Practices.Prism.Events.CompositePresentationEvent<JobCompleted>
{ }
public class JobCompleted
{
}
1) Why you using if (_jobIsRunning) ?? You calling callback in any case.
2) Prism will only bring you the event - and according to your question - Prism IS rising and passing the event to you - so it's not a Prism question - it seems that whatever called by callback is not working.
So we need to see more on what is called by callback and another thing: in Prism case you calling the callback on ThreadOption.UIThread ThreadPool so - double check if any other thread already lock the UI thread when you calling callback
My problem is that I should not have used an anonymous method in my subscribe. Prism does not seem to support it. Some are calling this a bug in Prism, I agree :) Not only can you not use an anonymous method but the method must be public.
Some references I found googling
http://greenicicleblog.com/2010/04/28/prism-event-aggregator-more-leaky-than-it-seems/
Execute same Prism Command from different ViewModels
I suspect this is in the Prism docs somewhere, I guess I just blew by it. If I set keepSubscriberReferenceAlice it works with the private method or anonymous method (which does make some sense now that I think about it). The funny thing is that in my sandbox project I cannot even compile with an anonymous method which uses privately scoped code. My live project allows it to compile but fails at runtime.
Edit:
Yup, it is in the docs
http://msdn.microsoft.com/en-us/library/ff921122%28v=pandp.40%29.aspx
Big yellow box 2/3 of the way down the page.

Concurrent ObservableCollection in Silverlight 5

I need a thread-safe (concurrent) version of ObservableCollection in Silverlight 5. I'm struggling to find a way to create one given the lack of multi-threading support in SL5 (no ReaderWriterLock, no Collections.Concurrent to speak of, etc).
I need the collection to support UI binding while being updated by another thread. It is not acceptable for my to dispatch all of my updates to the UI thread when the process runs in the background. Ideally, the background process is free to update the collection as needed and the UI receives notifications as changes occur. This is possible with .NET 4 and I've found ways to accomplish this for WPF but nothing for SL. I can't use the WPF examples because they rely on ReaderWriterLock which, AFAIK, is not present in SL5.
Any direction and/or examples is appreciated.
UPDATE
Following the asynchronous communication pattern used (required) in Silverlight, the 'callback' method, or handler, runs on a different thread. Using the TPL (as we do), this is the task's Continuation.
Because this code runs on a different thread, any statements that affect the ObservableCollection have to be marshalled back to the UI thread. This means that the process logic and time are now consuming the resources of the UI thread.
The point of the concurrent collections in .NET is to allow producers and consumers to run in different threads yet seamlessly work with the shared data in the collection. The 'producers' in a SL client application will be the async callback or task continuation with the 'consumers' being the UI which is bound to the collection.
I also ran into this problem repeatedly, which caused me to go down the same road you're looking at. There is a library that has helped me immensely with this task:
http://ch.codeplex.com/
I've implemented my own ConcurrentObservableCollection using the TinyReaderWriterLock and implementing IList, INotifyCollectionChanged, INotifyPropertyChanged
I used this blog post as a starting point.
http://www.deanchalk.me.uk/post/Thread-Safe-Dispatcher-Safe-Observable-Collection-for-WPF.aspx
In my version I allow all calls to execute on the calling thread and only marshal the INotifyCollectionChanged and INotifyPropertyChanged calls back to the UI Thread like this:
public void Add(T item)
{
mSyncLock.LockForWriting();
innerCollection.Add(item);
mSyncLock.ReleaseForWriting();
var index = IndexOf(item);
OnNotifyPropertyChanged(COUNT_PROPERTY);
OnNotifyPropertyChanged(INDEXER_PROPERTY);
OnNotifyCollectionChanged(NotifyCollectionChangedAction.Add, item, index); // This is an overload of OnNotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
}
where
protected virtual void OnNotifyCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (CollectionChanged == null) return;
ThreadSafeInvoke(() => CollectionChanged(this, e));
}
and
private static void ThreadSafeInvoke(Action action)
{
if (Deployment.Current.Dispatcher.CheckAccess())
{
action.Invoke();
}
else
{
Deployment.Current.Dispatcher.BeginInvoke(action);
}
}
This has worked well for me. There is a small performance hit involved with the locking, but it's not significant for most uses.

Asynchronous WCF Services in WPF - events

I am using WCF services asynchronously in a WPF application. So I have class with all the web service. The view models call the method in this proc, which in-turn calls the web service.
So the view Model code looks like this:
WebServiceAgent.GetProductByID(SelectedProductID, (s, e)=>{States = e.Result;});
And the WebService agent looks like:
public static void GetProductByID(int ProductID, EventHandler<GetProductListCompletedEventArgs> callback)
{
Client.GetProductByIDCompleted += callback;
Client.GetProductByIDAsync(ProductID);
}
Is this a good approach? I am using MVVM light toolkit. So the View Model static, so in the lifetime of the application, the view model stays. But each time the view model calls this WebServiceAgent, I think I am registering an event. But that event is not being unregistered.
Is this a problem. Lets say the view Model is called for 20 - 30 times. I am inserting some kind of memory leak?
Some helpful information, based on the mistakes I learned from myself:
The Client object seems to be re-used all the time. When not unregisering event handlers, they will stack up when future invokations of the same operations finish and you'll get unpredictable results.
The States = e.Result statement is executed on the event handler's thread, which is not the UI dispatcher thread. When updating lists or complex properties this will cause problems.
In general not unregistering event handlers when they are invoked is a bad idea as it will indeed cause hard to find memory leaks.
You should probably refactor to create or re-use a clean client, wrap the viewmodel callback inside another callback that will take care of unregistering itself, cleaning up the client, and invoking the viewmodel's callback on the main dispatcher thread.
If you think all this is tedious, check out http://blogs.msdn.com/b/csharpfaq/archive/2010/10/28/async.aspx and http://msdn.microsoft.com/en-us/vstudio/async.aspx. In the next version of C# an async keyword will be introduced to make this all easier. A CTP is available already.
Event handlers are death traps and you will leak them if you do not "unsubscribe" with "-=".
One way to avoid is to use RX (Reactive Extensions) that will manage your event subscriptions. Take a look at http://msdn.microsoft.com/en-us/data/gg577609 and specifically creating Observable by using Observable.FromEvent or FromAsync http://rxwiki.wikidot.com/101samples.
This is unfortunaltely not a good approach.
I learned this the hard way in silverlight.
Your WebserviceAgent is probably a long-life object, whereas the model or view is probably short-life
Events give references, and in this case the webservice agent, and wcf client a reference to the model. A long lifeobject has a reference to a short life object, this means the short life object will not be collected, and so will have a memory leak.
As Pieter-Bias said, the async functionality will make this easier.
Have you looked at RIA services? This is the exact problem that RIA services was designed to solve
Yes, the event handlers are basically going to cause a leak unless removed. To get the near-single line equivalent of what you're expressing in your code, and to remove handlers you're going to need an instance of some sort of class that represents the full lifecycle of the call and does some housekeeping.
What I've done is create a Caller<TResult> class that uses an underlying WCF client proxy following this basic pattern:
create a Caller instance around an existing or new client proxy (the proxy's lifecycle is outside of the scope of the call to be made (so you can use a new short-lived one or an existing long-lived one).
use one of Caller's various CallAsync<TArg [,...]> overloads to specify the async method to call and the intended callback to call upon completion. This method will choose the async method that also takes a state parameter. The state parameter will be the Caller instance itself.
I say intended because the real handler that will be wired up will do a bit more housekeeping. The real callback is what will be called at the end of the async call, and will
check that ReferenceEquals(e.UserState, this) in your real handler
if not true, immediately return (the event was not intended to be the result of this particular call and should be ignored; this is very important if your proxy is long lived)
otherwise, immediately remove the real handler
call your intended, actual callback with e.Result
Modify Caller's real handler as needed to execute the intended callback on the right thread (more important for WPF than Silverlight)
The above implementation should also have separate handlers for cases where e.Error is non-null or e.Cancelled is true. This gives you the advantage of not checking these cases in your intended callback. Perhaps your overloads take in optional handlers for those cases.
At any rate, you end up cleaning up handlers aggressively at the expense of some per-call wiring. It's a bit expensive per-call, but with proper optimization ends up being far less expensive than the over-the-wire WCF call anyway.
Here's an example of a call using the class (you'll note I use method groups in many cases to increase the readability, though HandleStuff could have been result => use result ). The first method group is important, because CallAsync gets the owner of that delegate (i.e. the service instance), which is needed to call the method; alternatively the service could be passed in as a separate parameter).
Caller<AnalysisResult>.CallAsync(
// line below could also be longLivedAnalyzer.AnalyzeSomeThingsAsync
new AnalyzerServiceClient().AnalyzeSomeThingsAsync,
listOfStuff,
HandleAnalyzedStuff,
// optional handlers for error or cancelled would go here
onFailure:TellUserWhatWentWrong);

MVVM Light DispatcherHelper & Unit Testing w/MSTest

I considered putting this as an additional question in this thread:
Unit testing with MVVM Light & DispatcherHelper
but as I delved into it, I think it's a little different.
I have one project containing view models/views, a separate project containing models, and a third separate unit test project (MSTest) containing tests for the models. I'm using MVVM Light's DispatcherHelper to help me do work in a background task, but to get errors from that task back to the UI.
The view model/view project has the App.xaml.cs file, which contains the OnStartup event handler, in which I've put the DispatcherHelper.Initialize() call. One of the VMs invokes a call to one of the model's long-running methods on another thread using delegate.BeginInvoke():
FileProcessDelegate processor = GenerateAddressingFile;
processor.BeginInvoke(FileGenerationComplete, null);
In this long-running method, it calls a utility method to send errors back to the UI. These are in the form of mvvm-light messages that are sent using the DispatcherHelper.CheckBeginInvokeOnUI()
internal static void ReportErrorToUi(IFileError error)
{
DispatcherHelper.CheckBeginInvokeOnUI(
() => Messenger.Default.Send(new GenericMessage<IFileError>(error), MessageTokens.ReportFileError));
}
This all seems to work fine in the app.
In one of the unit test classes for the model, I attempt to check that the long-running method correctly sends messages when errors occur. In that test class, I have a call to DispatcherHelper.Initialize() in the MSTest class initialization method.
#region Additional test attributes
//
//You can use the following additional attributes as you write your tests:
//
//Use ClassInitialize to run code before running the first test in the class
[ClassInitialize]
public static void MyClassInitialize(TestContext testContext)
{
DispatcherHelper.Initialize();
}
The test registers for the message that should be sent, then calls the model's method directly, without invoking it on a separate thread. As I understand it, because the call to send the message is wrapped by DispatcherHelper.CheckBeginInvokeOnUI() in the model, it should do the right thing regardless of whether it is occurring on a background thread or on the UI thread.
In the first test of this class that checks the method, everything works fine. The test receives the error messages being sent back and passes with flying colors.
When subsequent tests in the same class run, the messages are never received by the test. When I've stepped through it on these subsequent tests, I notice that when I get to the DispatcherHelper.CheckBeginInvokeOnUI() method, the DispatcherHelper.UIDispatcher.Thread instance says it's dead.
Any thoughts?
I'm not sure if this solution is something that can be included in Mvvm Light, or if it violates some base premises of the framework, but here's what I did to get this to work:
I made a custom local version of the DispatcherHelper class that has one minor difference from what's in Mvvm Light, namely the logic in the Initialize() method:
public static void Initialize()
{
if (UIDispatcher != null &&
UIDispatcher.Thread.IsAlive)
{
return;
}
UIDispatcher = Dispatcher.CurrentDispatcher;
}
Here, the change is the addition of:
&& UIDispatcher.Thread.IsAlive
to the condition. This allows me to call DispatcherHelper.Initialize() in the MyTestInitialize() method of my unit test class. That way, if the previous thread that the UIDispatcher was associated with has died, the DispatcherHelper gets the new Dispatcher/Thread that this current test method will be run on.
Apparently, in the VSTS Testing framework, there is not a "central" thread that acts like the UI thread in an application. The MyClassInitialize() method was executed on one thread, and then the tests were run on a completely different thread. The Mvvm Light definition wouldn't let me hook the DispatcherHelper up to the new test thread by calling DispatcherHelper.Initialize() again because the UIDispatcher wasn't null, it's thread was just dead.
Testing async code is tricky. Typically, if it works once, and then not anymore, it sounds like you are not synchronizing your threads correctly. In your test method (main thread), are you waiting for the background thread to execute?
Jonas Follesoe wrote a few good articles about async unit testing in Silverlight, for example http://jonas.follesoe.no/2007/09/18/unit-testing-event-based-asynchronous-code/. This is typically how I unit test my async code too.
Hope this helps,
Laurent

Resources