Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Getting back on the UI thread in Silverlight

0.00/5 (No votes)
27 Apr 2010 1  
When writing a demo for the Dutch Code-camp  I ran into issues getting back on the UI thread after calling a webservice. The call to the webservice was made from the UI thread, but the callback was made on a different thread. The System.Threading.SynchronizationContext class held the...

When writing a demo for the Dutch Code-camp  I ran into issues getting back on the UI thread after calling a webservice. The call to the webservice was made from the UI thread, but the callback was made on a different thread. The System.Threading.SynchronizationContext class held the solution.


The System.Threading.SynchronizationContext class is a base class that provides a thread-free context. It contains a read-only static property named Current, which gets the thread from which it is requested. When the current context is kept while the asynchronous call to a webservice is made, it can be used the call method in that context. The SynchronizationContext.Post can do this asynchronous, the SynchronizationContext.Send can do this synchronous.


Sample


Let me try to explain with a small sample which is taken from the code-camp demo.


The GetSearch(string searchText) method is called, which begins the call to the Bing API.



public class BingModel : IBingModel
{
    // this string is used to make the actual call to the bing API. 
    // the blancs are filled in when SearchBing method is called
    const string BingRequestURL =
        "http://api.bing.net/json.aspx?AppId={0}&Version=2.2&"
        +"Market=en-US&Query={1}&Sources=web&Web.Count={2}";
 
    // the request is kept so it can be used to handle the response
    private WebRequest request;
 
    // the SearchBing method is called from the UI thread
    //(note: //you can get your AppId at http://bing.com/developers)
    public void SearchBing(string searchText, string appId)
    {
        //the blancs are filled in  
        string requestString = 
            string.Format(BingRequestURL, 
                          appId, 
                          HttpUtility.UrlEncode(searchText),
                          20); //20 results will be givin.
        //a new request is made.
        request = HttpWebRequest.Create(requestString);
        
        //the getting of the response is started. The OnRequestCompleted 
        //method is provided so it can be called when the request is 
        //completed. The Current SynchronizationContext is provided as 
        state so it can be handled by the result.
        request.BeginGetResponse(OnRequestCompleted, 
                                 SynchronizationContext.Current);
    }
 
    //when the request is completed this method is called
    private void OnRequestCompleted(IAsyncResult ar)
    {
        //the response is extracted from the result and read thru a stream.
        var webResponse = (HttpWebResponse)request.EndGetResponse(ar);
        var response = new StreamReader(webResponse.GetResponseStream());
        
        //Because a string of Json is returned by the service, this string is 
        //parsed into a JsonObject.
        var json = JsonObject.Parse(response.ReadToEnd());
 
        //the ExtractResults method (defined below) is used to create 
        //an enumeration of the results
        IEnumerable<BingResult> ress = ExtractRestults(json);
 
        // this method (defined below) is used to fire a custom event on the UI thread
        // the state is provided as Synchronization context along with the json results
        InvokeSearchBingCompletedEvent(ar.AsyncState as SynchronizationContext, ress);
    }
    
    private void InvokeSearchBingCompletedEvent(SynchronizationContext context, 
                                                IEnumerable<BingResult> ress)
    {
        if (context != null) // just in case the context has become null somehow
            // call an anonymous method asynchronous on the context that was used to start 
            //the search
            context.Post((e) => 
                     {
                         if (SearchBingCompleted != null) 
                             //raise the event
                             SearchBingCompleted(this, new SearchBingCompletedArgs() 
                                                   {
                                                       SearchResults = ress.ToList()
                                                   }
                                 );
                     }, null);
    }
 
    // Extract search result from Json returned by Bing API  
    private static IEnumerable<BingResult> ExtractRestults(JsonValue json)
    {
        var results = json["SearchResponse"]["Web"]["Results"] as JsonArray;
 
        return from res in results
               select new BingResult()
                          {
                              Title = res["Title"],
                              Url = res["Url"]
                          };
    }
    
    // the definition of the event handler
    public event EventHandler<SearchBingCompletedArgs> SearchBingCompleted;
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here