SilverBullet, Silverlight

SilverBullet #13 – System.Threading.SynchronizationContext

silverbulletI’d like to provide you with a SilverBullet™, a small snippet of Silverlight, a class or namespace hidden in the silverlight .NET framework, to help you out in times of need. It’s not to learn, but something to keep in your pocket. Just remember it’s there and you’re safe.

When writing the demo for the 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;
}

 

 

 

Leave a Reply

Seo wordpress plugin by www.seowizard.org.
%d bloggers like this: