In
the world of asynchronous programming, and especially in the world of
distributed asynchronous programming, errors are a fact of life and
should be expected. Rx.NET Observers provide a separate OnError event handler to deal with unforeseen errors that may arise. For instance, to make the WeatherRx application more robust, let's add an OnError handler to the weather.Subscribe call. The resulting code would look like this:
weather.ObserveOn(Deployment.Current.Dispatcher).Subscribe(evt =>
{
if (evt.EventArgs.Result.Details != null)
{
lblWeatherFahrenheit.Text = "Current Weather, Fahrenheit: " +
evt.EventArgs.Result.Details[0].MinTemperatureF.ToString() + " - " +
evt.EventArgs.Result.Details[0].MaxTemperatureF.ToString();
lblCelsius.Text = "Current Weather, Celsius: " +
evt.EventArgs.Result.Details[0].MinTemperatureC.ToString() + " - " +
evt.EventArgs.Result.Details[0].MaxTemperatureC.ToString();
imgWeather.Source = new BitmapImage(new Uri(evt.EventArgs.Result.Details[0].WeatherImage,
UriKind.Absolute));
}
},
ex => {
Deployment.Current.Dispatcher.BeginInvoke(() => lblStatus.Text = ex.Message);
}
);
Note the somewhat cryptic (it's a lamda expression and it uses a lambda expression within its own body) use of the Deployment.Current.Dispatcher.BeginInvokeOnError statement to get around cross-thread access issues discussed previously. In the preceding code, the
handler simply displays the exception text, but there is nothing
stopping you from dissecting an error thoroughly and providing a
possible corrective action. For instance, if the web service is not
available at the address specified, you may retry your call to a
different location of the web service. Rx.NET also has exception
handling operators Catch, Finally, OnErrorResumeNext, and Retry,
which aid in recovering from errors. You will explore some of those in
the next section as we discuss some potential ways of handling
intermittently available data connections on the phones.