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.

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was 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 Microsoft MVP.
This entry was posted in Data, Essentials, Reactive and tagged . Bookmark the permalink.

11 Responses to Asynchronous Callbacks with Rx

Comments are closed.