Asynchronous Callbacks with Rx

Reactive Programming, Posting # 8

One of the tried and true patterns in .NET programming is to call an Asynchronous service (e.g., BeginGetResponse) and to then provide a callback to a second method for when the call completes.  This can get very complex very quickly if you have chained calls (call this, then when you finish, call that)

Let’s take a look at how you can simplify such a call with Rx by examining making a HTTPWebRequest.

We’ll begin by creating a dead-simple UI, consisting of a TextBox (to type in a URL), a TextBlock (to display the returned HTML) and a button (to kick things off).  For simplicity, we* created this as a WPF application, though you could certainly do the same in Silverlight or Windows Phone,

* This example was worked through with Paul Betts who has forgotten more about Rx than I’ll likely ever know.

 

<Window
   x:Class="SimpleAsyncCanonical.MainWindow"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="MainWindow"
   Height="350"
   Width="525">
   <Grid>
      <Grid.RowDefinitions>
         <RowDefinition
            Height="1*" />
         <RowDefinition
            Height="3*" />
         <RowDefinition
            Height="1*" />
      </Grid.RowDefinitions>
      <TextBox
         Name="URI"
         Width="200"
         Height="30"
         Grid.Row="0" />
      <TextBlock
         Name="WebContents"
         Text="Ready..."
         TextWrapping="Wrap"
         Grid.Row="1" />
      <Button
         Grid.Row="2"
         Name="Go"
         Content="Go"
         HorizontalAlignment="Center"
         VerticalAlignment="Center" />
   </Grid>
</Window>

We begin by creating an HTTPWebRequest by calling WebRequest.Create and passing in the Url that the user types into our text box.

 private IObservable<WebResponse> getUrl( string Url )
 {
    var httpWR = 
      ( HttpWebRequest ) WebRequest.Create( Url );

Without Rx we’d now call httpWR.BeginGetResponse and set in motion the two two-method asynchronous pattern. Instead, we’ll use Rx’s FromAsyncPattern<T> where T is the return type we’re looking for,

var getResponse = 
   Observable.FromAsyncPattern<WebResponse>( 
   httpWR.BeginGetResponse, httpWR.EndGetResponse );

This returns a function that returns an IObservable<WebResponse> which is assigned to getResponse.  We then return the results of calling that function,

 return getResponse( );

 

Calling the func actually retrieves the html as an Observable collection.  We now need to translate that result into a standard string and then assign it to the Text property of the TextBlock. All of this is done in the button’s click event handler.  Here is the complete source code for context,

using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Windows;

namespace SimpleAsyncCanonical
{
   public partial class MainWindow : Window
   {
      public MainWindow( )
      {
         InitializeComponent( );
         Go.Click += new RoutedEventHandler( Go_Click );
      }

      private void Go_Click( object sender, RoutedEventArgs e )
      {
         getUrl( URI.Text ).ObserveOnDispatcher( ).Subscribe( x =>
         {
            var ms = new MemoryStream( );
            x.GetResponseStream( ).CopyTo( ms );
            string s = Encoding.UTF8.GetString( ms.GetBuffer( ) );
            WebContents.Text = s;
         } );
      }

      private IObservable<WebResponse> getUrl( string Url )
      {
         var httpWR = 
            ( HttpWebRequest ) WebRequest.Create( Url );
         var getResponse = 
            Observable.FromAsyncPattern<WebResponse>( httpWR.BeginGetResponse, httpWR.EndGetResponse );
         return getResponse( );
      }
   }
}

The key is the first highlighted line, which shows the call to GetUrl passing in the Text from the text block, then ObserveOnDispatcher which marshals the results to the UI thread avoiding an exception, and then Subscribe, which subscribes to the results and modifies the results to a displayable string.

Share

About Jesse Liberty

Jesse Liberty is an independent consultant and programmer with three decades of experience writing and delivering software projects. He is the author of 2 dozen books and multiple Pluralsight courses, and has been a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Xamarin Certified Mobile Developer and a Xamarin MVP, Microsoft MVP and Telerik MVP.
This entry was posted in Data, Essentials, Reactive and tagged . Bookmark the permalink.

13 Responses to Asynchronous Callbacks with Rx

  1. test website says:

    I do not even know how I ended up right here, but I assumed this put up was great. I don’t know who you are but certainly you’re going to a famous blogger in the event you aren’t already. Cheers!|

  2. James says:

    void Go_Click(object sender, RoutedEventArgs e)
    {

    getUrl(Uri.Text).ObserveOnDispatcher().Subscribe(a =>
    {
    var ms = new MemoryStream();
    a.GetResponseStream().CopyTo(ms);
    string s = System.Text.Encoding.UTF8.GetString(ms.GetBuffer());
    WebContents.Text = s;
    });

    }
    it gives me error lamba expression cannot coverted to type system.io.observer

  3. @Fallon That’s one thing I’m not really clear about. If the Rx Framework isn’t ‘supported’ (IOW, by Microsoft Support), then I’m not really clear how Rx today is ‘better’ (WRT support/production) compared to the async CTP.

    IOW, by now the issues with the CTP are likely fairly well known, and as has been explained pretty well, it’s another ‘compiler rewrite magic’ feature. Since the runtime is (by default) based on the TPL, which was in .NET 4, it seems like it’d be pretty stable (even if the build for Silverlight only exists in that CTP currently).

    If you don’t trust or don’t want to rely on the compiler-rewrite bit, the TPL build for Silverlight within the async CTP sure seems it’s a better option today than using Rx.

    I’d love to hear the other side and have someone explain what I’m missing and why Rx today is better.

  4. Fallon says:

    @James Manning

    You’re right, unless you need this asap, it’s better to wait for the async stuff.

    Rx is good right now for other things, but I LOVE the new async much better.

  5. What are the pros/cons of doing this as opposed to using the async CTP and its build of the TPL? It’s not clear to me whether the Rx Framework is officially ‘supported’, so it seems like using the async CTP (with the new keywords) is ‘best’ and if that’s not an option for you, using the TPL build in its Silverlight dll.

    That seems like you’re writing better code (from a long-term POV) that will be more inline with the async support which will default to using the TPL.

    This isn’t to say Rx doesn’t work for async chaining (it clearly does), but the TPL seems like a much better fit for “do this, then do this, then do this” (each ‘thing’ having one output) especially WRT exception handling and cancellation.

    For multiple observables that fire multiple times (like the events around drag-drop), Rx is great. When things will fire exactly once (a task), TPL/Task seems to make more sense to me.

  6. Shai leib says:

    This info is great, because I was looking for something similar to chaining events using tasks like in the TPL library.

    FYI – some of the code s uppers are truncated on the right side when viewing in mobile browser.

  7. Tim Cochran says:

    @Kefala Jesse’s latest post appears to address the chaining example. I am reading it now…

  8. Anonymous says:

    @Kefala Not directly, but Jesse did create a new post that comes closer.

  9. Pingback: Asynchronous Callbacks with Rx | www.nalli.net

  10. Devin says:

    So it depends on how you want to chain calls. Say you want to go download two websites at the same time, and display thier output one right after the other. For this you can use the Concat to merge the two streams of input and just append to the text box.

    If you want to download one website, and then have the result of that download a diffrent website, you would just in your lamba function, have a new getUrl( xxxxx ).ObserveOnDispatcher( ).Subscribe( result2 => {}) , where xxxx is the part that you parsed out of the result of the first call.

  11. Kefala says:

    @Tim Cochran did you get an answer to this? It’s exactly what I’m trying to do as well.

  12. Tim Cochran says:

    Thanks for the example. How about one with a few ‘chained’ calls (with the results of next call dependent on the previous call)?

    My Silverlight application uses several chained calls (both WCF and RIA Services calls) and so far I haven’t found many Rx example of multiple, chained async calls.

  13. Pingback: Tweets that mention Asynchronous Callbacks with Rx | Jesse Liberty -- Topsy.com

Leave a Reply

Your email address will not be published.