Mobile Zone is brought to you in partnership with:

Den is a DZone Zone Leader and has posted 460 posts at DZone. You can read more from them at their website. View Full User Profile

5 minute Observable.FromAsyncPattern sample for Windows Phone 7

11.11.2010
| 14126 views |
  • submit to reddit

Not lots of developers know that Windows Phone 7 SDK comes pre-bundled with Reactive Extensions (Rx) that dramatically simplify work with asynchronous calls. In this article, I am going to focus particularly on Observable.FromAsyncPattern that allows developers combine two Begin/End calls (for example, when working on reading streams) into a single asynchronous call, and if you are familiar with basic function composition, this won't be too hard of a topic to understand.

For now, rather than talk about the theory behind FromAsyncPattern, let's take a look at a specific example - handling a web request. The standard way of doing this would be initializing a HttpWebRequest and asynchronously getting the response via BeginGetResponse (also passing a callback that will handle it).

HttpWebRequest request = (HttpWebRequest)WebRequest.Create("http://bing.com");
request.Method = "GET";
request.BeginGetResponse(new AsyncCallback(GetResponse), request);

So the callback can handle the response the way you want:

void GetResponse(IAsyncResult res)
{
HttpWebRequest request = (HttpWebRequest)res.AsyncState;
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(res);
Debug.WriteLine(response.ContentType);
}

Rx allows you to go around the whole async call in one line. So to say:

var n = Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)();

If you analyze n, you will see that its type is defined as IObservable<WebResponse>. In its core, IObservable might be a new interface to some of the developers that are currently reading this. So let's dive into some theory now.

Usually, when you work with specific enumerations, there is IEnumerable<T>/IEnumerator<T> that can help you navigate through a generic collection of returned objects. GetEnumerator (caled out of IEnumerable) will get the associated IEnumerator, that will go through each object in the collection (via MoveNext) setting the Current value to the selected object. A pretty simple concept that shows how data can be pulled from a collection.

IObservable on the other side is the complete opposite of IEnumerable because it reverses the process - instead of data being retrieved by the program via IEnumerator, it is now pushed back to it by the environment via IObserver, with which the application interacts (talking about the concept of interface duality here).

When you need to obtain the data that is being pushed as a result of the call (in this case, in n), you need to use Subscribe and pass a handling method:

n.Subscribe(HandleResult);

What's done behind the scene here is that an observer is actually created that will be handling the pushed data. It might be a bit confusing as to why the returned type is IDisposable and the answer is simple - so that it will be possible to un-subscribe and dispose the observer once there is no more need to receive pushed data.

And then again, you can handle the result as you want:

void HandleResult(WebResponse res)
{
Debug.WriteLine(res.ContentType);
}

Of course, this entire operation can be unified in one line:

Observable.FromAsyncPattern<WebResponse>(request.BeginGetResponse, request.EndGetResponse)().Subscribe(HandleResult);

One thing to remember here is that on Windows Phone 7, the maximum number of passed parameters is 2 (Func<T1,T2,TResult>) - in a regular application this extends to 29 overloads and 14 possible parameters. Working directly with System.Linq.Observable is currently not possible on the phone and will fail to compile, the issue being "Error 427 'FromAsyncPattern' is not supported by the language".

On the device itself, many asynchronous tasks can be simplified by using FromAsyncPattern, since you can combine various asynchronous functions - even the least common ones, since there are some overloads present that allow you to pass additional parameters that will be passed to the asynchronous functions. One important consideration to remember is that there should be the starting and end methods (to start the async processing and to end it accordingly). 

Comments

Sony Arouje replied on Tue, 2010/11/16 - 2:42am

As Den explained Rx is a very good framework to perform Async calls. One advantage I like in Rx is we can place the calls in ThreadPool and dispatched to CurrentThread once it's done. That way it wont block the UI. Below snippet will do the same

WebClient wc = new System.Net.WebClient();

var o = Observable.FromEvent(wc, "DownloadStringCompleted") .ObserveOn(Scheduler.ThreadPool) .Select(newString => newString.EventArgs.Result);

o.ObserveOn(Scheduler.Dispatcher).Subscribe(s => EventAggregatorHelper.EventAggregator.Publish(new TimelineMessage(LoadPublicTimeLines(s.ToString()))));

wc.DownloadStringAsync(uri);

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.