views:

456

answers:

2

I'm trying to update my Silverlight 4 UI approx every 1/2 second with new data. I've hooked into a WCF service using net.tcp binding and issuing callbacks from the server. To make sure I get the data from the service as quickly as possible I've started up my proxy on a backround worker inside of my Silverlight App.

My question is, how do I get the results from the callback and update the ObservableCollection that is bound to a datagird? I've tried a number of different ways and keep getting the dreaded cross-thread error.

+3  A: 

Use the Dispatcher BeginInvoke. For example:-

 private void MyCallback(object sender, SomeArgsClass e)
 {
     // perhaps some extraction of a payload or something
     Deployment.Current.Dispatcher.BeginInvoke( () =>
     {
        // Code you need to run on the UI thread.
     });

     // Note code may or may not exit here before code above has completed.
     // So be careful with disposable types etc.
 }
AnthonyWJones
+2  A: 

There are several approaches you can take:

  • use Deployment.Current.Dispatcher from the background thread, and do a Deployment.Current.Dispatcher.CheckAccess() call on it

  • pass the dispatcher from the UI component that starts the background thread, and use that handle to perform the CheckAccess() call

  • this is my preferred option: pass a delegate (callback) to the background thread, when it has new data it calls that delegate, and that delegate lives within the UI control - it can then use the Dispatcher available on the UI control

The pattern for this sort of thing is:

private void DoMyUIUpdate(List<object> updates)
{
    if (Deployment.Current.Dispatcher.CheckAccess())
    {
        //do my work, update the UI
    }
    else
        Deployment.Current.Dispatcher.BeginInvoke(new Action<List<object>>(DoMyUIUpdate), updates);
}
slugster
If I use option 3 (the preferred) I lose out on all of the performance enhancements that starting the proxy on the worker thread gains, since the callbacks would be issued to the UI thread. Check this out:http://tomasz.janczuk.org/2010/03/comparison-of-http-polling-duplex-and.html
DavyMac23
No you don't - any sort of UI updating has to be done on the UI thread, invoking anything on the Dispatcher means it gets marshalled on to the UI thread. The *//do my work* could be as simple as updating the collection that your UI is bound to. The "performance enhancement" that you talk of is retrieving the data in a way that doesn't block the UI thread - *updating the UI is not done from the background thread*, no matter which method you use when dealing with the Dispatcher.
slugster