views:

43

answers:

2

Hi guys,

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

A: 

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?

Ken Smith
It is not that complicated. But for example, an entity created for RIA Services, should not be done in the UI Thread, it takes too long then the UI freeze. So all that concerns the RIA context running on a background thread and my UI is more fluid.
Vincent BOUZON
I've done similar stuff in my projects, where I move all WCF communication to background threads using ThreadPool.QueueUserWorkItem(). It's not so much that it makes things faster as that it makes the UI appear to run more smoothly. But then I basically do what HiTech Magic's answer does, namely, use Dispatcher.BeginInvoke() to marshal the data back onto the UI thread when necessary. But I'm not using RIA Services, so I haven't had to worry about synchronizing access to its context. Would a simple lock object (e.g., "lock(myRiaContext){}") give you the synchronization you need?
Ken Smith
Yes, of course, I also use a lock in what PostSharp injected.
Vincent BOUZON
+1  A: 

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.

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;
    });
Enough already