Skip to main content

WP7Contrib: Timing out HTTP requests on Windows Phone 7

This code uses change set #68097 of the WP7Contrib - http://wp7contrib.codeplex.com/SourceControl/changeset/changes/68097

When doing communications over HTTP we often want to set a timeout for the response.  We want the ability to handle the timeout in a timely manner when the communication with a remote server has taken too long. When using the full version of the .Net framework we have the ability to control this precisely using the HttpWebRequest.Timeout property. The default value is set to 100 seconds. Unfortunately the ability to change this property is not supported on the Windows Phone 7 platform and I suspect the value is set to 100 seconds (should test this hypothesis). Looking around on the internet there are several approaches to get around this problem using the DispatcherTimer class and explicitly disposing of the request when the timeout has been exceeded, see an example here.

When using our ResourceClient to do RESTful communication over HTTP we can leverage the power of Rx (reactive extensions) and use the 'Timeout()' method - nice simple example here. This method throws a TimeoutException when the timeout occurs.

The following example shows the implementation for the button click code-behind using the previous ResourceClient example (Google Weather API on WP7):

private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
      this.weatherResource.Get<xml_api_reply>(encoder.Encode(location.Text))
         .Timeout(TimeSpan.FromMilliseconds(10000))
         .ObserveOnDispatcher()
         .Subscribe(result =>
            {
               var text = string.Format("Current Temp. (Celsius) in {0}: {1}",
               location.Text,
               result.weather[0].current_conditions[0].temp_c[0].data);
            
               Debug.WriteLine(text);
            },  
            exn => Debug.WriteLine("Failed, exception - " + exn.Message),
            () => Debug.WriteLine("Completed!"));
}

When executed the code outputs the following in Visual Studio:


To demonstrate a timeout we can lower the value to 10 ms, this gives the following output in Visual Studio:


Now setting a 'reasonable' value this should cover 90% of cases, but there are going to be times when we will receive timeout exceptions unexpectedly.  When this happens we want to employ a retry strategy, again Rx provides a method for this - 'Retry()'. Shown below is the code with a retry strategy of 3 attempts:

private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
      this.weatherResource.Get<xml_api_reply>(encoder.Encode(location.Text))
         .Timeout(TimeSpan.FromMilliseconds(10))
         .Retry(3)
         .ObserveOnDispatcher()
         .Subscribe(result =>
            {
               var text = string.Format("Current Temp. (Celsius) in {0}: {1}",
               location.Text,
               result.weather[0].current_conditions[0].temp_c[0].data);
            
               Debug.WriteLine(text);
            },  
            exn => Debug.WriteLine("Failed, exception - " + exn.Message),
            () => Debug.WriteLine("Completed!"));
}

When executed the code outputs the following in Visual Studio:


The above shows 3 attempts to access the remote server and we finally see the exception bubbling up and being handled.

Now we have to decide what a 'reasonable' value for timeout is and I believe this is dependent on the application you're building and the remote (back end) services you're using. If you're communicating with an enterprise level back end  (e.g. Google API) then you're going to be able to get away with a lower value. I would start with a value around  60 seconds and do testing in the field.  When choosing a value, it is impolrtant to remember that the maximum amount of time for making a request is going to be:

        Time out x Retry = Maximum total time.

         20 secs x 3 = 60  secs

So a user could be waiting for 60 seconds for data to be returned and displayed.

There is one caveat to this strategy and that is the hard coded value used by the HttpWebRequest class. If as I suspected this is hard coded to 100 secs as described by MSDN for the desktop version of .Net, then we will not be able to set a timeout greater than 100 secs.  I've not been able to test this just yet.

So the code examples above demonstrate the use of timeout & retry with the ResourceClient directly in the code-behind.

I've also updated the weather service implementation and what you now start seeing is the cleaner approach of using the service from the code-behind (or ideally from a view model) - the service is responsible for managing the retry strategy and the code-behind use of the service has not been modified.

You can find the demo application 'CommunicationTimeout' in the Spikes directory of the WP7Contrib code base. Shown below is a screenshot from the demo application.







Comments

Popular posts from this blog

Integrating jasmine into Visual Studio 2010/2011 beta

Following on from my previous post about testing javascript with jasmine. I was interested to explore integration into visual studio 2010 so I could run them along side test written in another language like C#. I found the VS 2010 extension Chutpah (pronounced  'hutz-pah'). This got me up and running with the ability to run test manually and to my surprised it worked by only have the SpecRunner.html file open. I didn't a csproj or sln file containing the javascript, it's clever enough to resolve all dependencies: Test results are render in the output window of VS 2010: This is good and I appreciate the work someone has done to get this far but I want more... I want integration into Resharper... A quick squizz on the inter'webs and I end posting a request on jetBrains forum , it looks like support is coming in R# 7. Then I thought lets check out the current beta and see, so off I go and boot Win8 and install R#7 beta and see if it's there yet... ...

Showing a message box from a ViewModel in MVVM

I was doing a code review with a client last week for a WPF app using MVVM and they asked ' How can I show a message from the ViewModel? '. What follows is how I would (and have) solved the problem in the past. When I hear the words ' show a message... ' I instantly think you mean show a transient modal message box that requires the user input before continuing ' with something else ' - once the user has interacted with the message box it will disappear. The following solution only applies to this scenario. The first solution is the easiest but is very wrong from a separation perspective. It violates the ideas behind the Model-View-Controller pattern because it places View concerns inside the ViewModel - the ViewModel now knows about the type of the View and specifically it knows how to show a message box window: The second approach addresses this concern by introducing the idea of messaging\events between the ViewModel and the View. In the example ...

WPF tips & tricks: Dispatcher thread performance

Not blogged for an age, and I received an email last week which provoked me back to life. It was a job spec for a WPF contract where they want help sorting out the performance of their app especially around grids and tabular data. I thought I'd shared some tips & tricks I've picked up along the way, these aren't probably going to solve any issues you might be having directly, but they might point you in the right direction when trying to find and resolve performance issues with a WPF app. First off, performance is something you shouldn't try and improve without evidence, and this means having evidence proving you've improved the performance - before & after metrics for example. Without this you're basically pissing into the wind, which can be fun from a developer point of view but bad for a project :) So, what do I mean by ' Dispatcher thread performance '? The 'dispatcher thread' or the 'UI thread' is probably the most ...