do { Engine.BlogAbout(".NET","Silverlight"); } while ( alive );  

Mark Monster

Mark Monster  

Silverlight Threading - Getting back to the UI thread

I’ve been investigating Silverlight for a few days. This will be the first post in the Silverlight category, more will follow. After experimenting with some user interface effects I started investigating the Silverlight Networking possibilities. I was able to get some results of a network call but I wasn’t able to get it to the UI in the first place. So after some investigation I found out about the following solution.

Working Asynchronously

It’s only possible to work asynchronously with the networking stack. This is to prevent a hanging UI / Browser. This is not a very bad decision although it makes communicating with Webservices and other things on the web more difficult. I’m not into explaining a lot of things about networking and working asynchronously in common. When starting an asynchronous call to for example a Webservice you will give the call a pointer to the function that needs to be called on completion. This could be for example a not working callback function.

1 void helper_ResponseComplete(HttpResponseCompleteEventArgs e) 2 { 3 resultBox.Text = e.Response; 4 }

What’s wrong?

The trouble with the code example above is the call to a UI part ‘resultBox’. You could thing that the asynchronous call works on a background thread and that the callback automatically works on the UI thread. This is not the case. The trouble is that you don’t really get an exception that your doing something wrong, just nothing happens. It took me some time to find out the solution.

A simple solution

Every DependencyObject has a property called Dispatcher. This Dispatcher has some intelligent code to make it possible to get back to the UI thread. It is possible to call ‘BeginInvoke’ on the Dispatcher property. This method will require an Action delegate or a simple delegate with eventually arguments. I really like the use of a lambda expression. The following code wraps the code from the previous example in a lambda expression and uses the Dispatcher to get it back to the UI.

1 void helper_ResponseComplete(HttpResponseCompleteEventArgs e) 2 { 3 Dispatcher.BeginInvoke(() => resultBox.Text = e.Response); 4 }

Luckily the code being executed is just one line, so this simple solution works. But most of the time the code to be executed on the UI thread is more than just one line. So we need a more advanced solution.

A more advanced solution

The Dispatcher property also has a method to check whether or not the current thread is the UI thread. The example below checks if the current thread is an UI thread, when not it calls itself with the same arguments but then through the Dispatcher. The advantage with this is the possibility to have a code block of a few lines within the else-statement.

1 void helper_ResponseComplete(HttpResponseCompleteEventArgs e) 2 { 3 if(!Dispatcher.CheckAccess()) 4 Dispatcher.BeginInvoke(()=>helper_ResponseComplete(e)); 5 else 6 { 7 resultBox.Text = e.Response; 8 } 9 }

Updates 17/07

Some of my readers had additions for this article. So it’s fair to add this information at the end of the article I think.

Bart Czernicki noted: When calling a WCF service through a proxy, the results get properly dispatched on the UI thread.

Brian Leahy noted: When making use of databinding the binding will take of resynchronizing. His code example:

1 void helper_ResponseComplete(HttpResponseCompleteEventArgs e) 2 { 3 this.Message= e.Response; 4 } 5 6 private String _message; 7 public String Message 8 { 9 get 10 { 11 if(_message == null) 12 { 13 GetMessageAsync(); 14 } 15 return _message; 16 } 17 set 18 { 19 _message = value; 20 PropertyChanged(value,”Message”); 21 } 22 }

Thanks for the comments!

6 Responses to “Silverlight Threading - Getting back to the UI thread”

  1. Bart Czernicki Says:

    Worth noting…when calling a WCF service through a proxy the result gets properly dispatched on the UI thread.

  2. Community Blogs Says:

    Silverlight Cream for July 15, 2008 — #325

    Mark Monster on SL Networking (2), Andy Beaulieu on finding XAML elements, chrishayuk with SL2 Wee Mee

  3. brian leahy Says:

    You are databinding you can let the binding take care of resyncronizing.

    void helper_ResponseComplete(HttpResponseCompleteEventArgs e)
    2 {
    3 this.Message= e.Response;
    8
    9 }

    private String _message;
    public String Message
    {
    get{
    if(_message == null)
    {
    GetMessageAsync();
    }
    return _message;}
    set{
    _message = value;
    PropertyChanged(value,”Message”);
    }

    }

  4. Mark Monster Says:

    @Bart:
    Thanks for your information, I will edit the article to include this information. I think it’s very strange that there’s a difference between using a WCF proxy and a WebRequest. I hope we will get more consistency in the final or future versions of Silverlight.

    @Brian
    Thanks for your reaction. I didn’t think about databinding yet, so this information is a good addition to my article. I will edit the article to include this information.

  5. Andrus Says:

    Is’nt this too complicated ? It is much simpler to add multiple lines method like

    () => {
    Line1;
    Line2;
    etc.
    }

  6. candihaze Says:

    Hi,

    I tried to add image but I don’t know how to do this
    Can anyone be kind to tell me how?

    thanks a lot

Leave a Reply