Reactive Extensions–FromAsync

Reactive Programming

I’ve been struggling with getting my head around the exact relationship between Rx’s approach to asynchronous programming and the traditional Begin/End pattern common in .NET programming.

With the help of Paul Betts I created a side by side example, starting with the traditional approach and then migrating it to Rx using Observable.FromAsyncPattern This, I think, makes the relationship much clearer.

We decided to use the Bing Translator service (again), but this time to start with the traditional approach.  We did this in WPF though we certainly could have done the exact same thing in Silverlight or Windows Phone.

We started by creating the world’s simplest (and ugliest) UI, consisting of a TextBox to put in text we want to translate, a button to start the translation, and a TextBlock to display the output.

 <Grid>
     <Grid.RowDefinitions>
         <RowDefinition
             Height="50*" />
         <RowDefinition
             Height="52*" />
         <RowDefinition
             Height="209*" />
     </Grid.RowDefinitions>
     <TextBox
         Height="23"
         HorizontalAlignment="Left"
         Margin="68,19,0,0"
         Name="Input"
         VerticalAlignment="Top"
         Width="260" />
     <Button
         Content="Translate"
         Grid.Row="1"
         Height="23"
         HorizontalAlignment="Left"
         Margin="68,17,0,0"
         Name="Translate"
         VerticalAlignment="Top"
         Width="252"
         Click="Translate_Click" />
     <TextBlock
         Grid.Row="2"
         Height="23"
         HorizontalAlignment="Left"
         Margin="72,27,0,0"
         Name="Output"
         Text="Ready..."
         VerticalAlignment="Top"
         Width="248" />
 </Grid>

Next, we added the Bing Translation Service to our application by adding a Service Reference to http://api.microsofttranslator.com/V2/Soap.svc (be sure to click on Advanced and to check the Generate Asynchronous Operations checkbox to ensure that you get support for Begin/End Translate).

The next step is to get a Bing API key, which we placed in MainWindow.xaml.cs as a constant,

const string AppId = "8E94xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxB2";

To translate the text, you begin by “newing up” a LanguageServiceClient, and then calling BeginTranslate on that client, passing in six strings and the delegate for your asynchronous callback, and the LanguageServiceClient as the async State.

The six strings are the AppId you just created, the text you want to translate, the language you want to translate from, the language you want to translate to, and then the content type and category, as shown here (we are translating from English to Spanish):

private void Translate_Click(
    object sender, RoutedEventArgs e )
{
    var client = new LanguageServiceClient();
    client.BeginTranslate(
        AppId,
        Input.Text,
        "en-US",
        "es-ES",
        "text/plain",
        "general",
        new AsyncCallback(TranslationCompleted),
        client );
}

When you run this code, the input text is passed to the translation service asynchronously, and when the service has completed the translation, your callback method is invoked.

The callback method extracts the LanguageServiceClient and then uses that to call EndTranslate (passing in the IAsyncResult object).  What it gets back is the translated string, which we can display by calling Dispatcher.BeginInvoke to put the writing of the text back onto the proper thread,

private void TranslationCompleted(
    IAsyncResult result )
{
    var client =
        result.AsyncState as LanguageServiceClient;
    string translated =
        client.EndTranslate( result );
    Dispatcher.BeginInvoke(
        new Action(() => Output.Text = translated ));

}

Translating to Rx

The purpose of that exercise was to see how this translates directly to Rx.  To do so, we created a second application, used the exact same Xaml, added the same service reference to Bing, and even added the same API string.

We then created a single method for the translation. We begin by again creating an instance of LanguageServiceClient, but this time instead of calling the asynchronous BeginTranslate method, we called Observable.FromAsyncPattern.  The types we passed in were seven strings (the six strings used as parameters in the non-async version of the call plus a string for the return type) and as parameters we passed in the two asynchronous call delegates.  The return of calling FromAsyncPattern was a func that takes six strings as parameters but returns an IObservable.

We invoke that func and it returns an IObservable of string which we then Subscribe to on the Dispatcher thread, passing in a lambda expression to put the text observed into the output box,

private void Translate_Click( object sender, RoutedEventArgs e )
{
    var client = new LanguageServiceClient();

    var translateFunc = Observable.FromAsyncPattern<
        string,
        string,
        string,
        string,
        string,
        string,
        string>(
                  client.BeginTranslate,
                  client.EndTranslate );

    var result = translateFunc(
        AppId,
        Input.Text,
        "en-US",
        "es-ES",
        "text/plain",
        "general" );

    result.ObserveOnDispatcher().Subscribe(
        x => Output.Text = x );
}

Putting these two applications side by side greatly clarifies how Rx translates an asynchronous pattern into a synchronous one that is easier to read and to maintain.

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 Linq, Mini-Tutorial, Reactive and tagged . Bookmark the permalink.

11 Responses to Reactive Extensions–FromAsync

  1. cipherz says:

    Are you saying that this replaces chaining? If so, what would that look like. I have an issue currently where I’m having to chain while making async socket calls and I would love to have some alternative to chaining because I think it’s horribly ugly.

    Can you give an example of this being used where someone would normally chain three async calls together.

    Thanks

    • ianicbass says:

      do something like this:

      var chainCalls = Observable.ForkJoin(
      Observable.Return((object)”a string”),
      Observable.Return((object)Guid.NewGuid()),
      Observable.Return((object)23),
      Observable.Return((object)33.44)
      );

      var calls = chainCalls
      .Select(c => c)
      .Subscribe(onNext: c =>
      {
      //do something with your data here…
      foreach (var item in c)
      {
      MessageBox.Show(item.ToString(), “test”,
      MessageBoxButton.OK);
      }
      });

      calls.Dispose();

  2. Tom says:

    Hey, am I doing exactly the same with Task.FromAsyc, ContinueWith, and a TaskScheduler obtained with FromCurrentSynchronizationContext?

  3. Pingback: Anonymous

  4. Pat Tormey says:

    mmm.. I though we were all switching to the Async Framework so we could just “await” the response without creating a new thread.
    http://msdn.microsoft.com/en-us/vstudio/async.aspx

    • The await pattern will definitely impact when you use Rx but they are not mutually exclusive, and the await pattern won’t do all that Rx does. Rx is really good at flattening more than one thread of execution.

  5. Peter says:

    I still don’t see what the benefits are. What problem does Rx solve that begin/end doesn’t ?

    • You really see the benefit of Rx with chained asynchronous events. This example was so simplified that the benefit isn’t manifest.

      • Peter Wone says:

        I’ve never understood why people have so much trouble with asynch. One day I had an epiphany, gathered all my state into a struct and started passing the struct as the the state object, and ever since then it’s all been dead easy. I find it hard to believe that this was an act of genius.

        Anders Hejlsberg gave a lengthy interview on the new await keyword, and I kind of reacted the same to that, except that I agree he’s made the code shorter and more obvious. I’m not convinced that Rx does that.

  6. Jay says:

    Jesse,

    A very nice article. Thank you.

    Finally, I understand “FromAsyncPattern” 🙂

    By the way, the link at the top (“Reactive Programming”) does not work.

    Jay.

Leave a Reply

Your email address will not be published.