Exposing asynchronous features to client code for Windows Phone 7

October 17, 2010 | Async

Today, line of Internet and multimedia-enabled smartphones have become popular. Fortunately if you are a .NET developer you can use your existing skills and language and target some of the most popular mobile operating systems.

Windows Phone 7 is a mobile operating system developed by Microsoft, and is the successor to their Windows Mobile platform. 

You can expose asynchronous features to client code using one of the following .NET Framework's Asynchronous Programming Models:

IAsyncResult has been around since .NET 1.0 and has been used in most BCL classes, while the main benefit of the EAP is that it integrates with the Visual Studio UI designers. You can learn how to properly implement the IAsyncResult interface (APM) from the excellent article on MSDN, Implementing the CLR Asynchronous Programming Model, by Jeffrey Richter.

In this post I will show you how easy it to use types implementing the IAsyncResult interface on Windows Phone 7. I will use the PowerThreading library because it provides a similar (not to say an improved) implementation of the one described in the original MSDN article. I will explain how to use it and how this becomes easier using the AsyncEnumerator class.

AsyncEnumerator class resides in the PowerThreading library. It is written by Jeffrey Richter and can be obtained from the Wintellect website.

The sample Windows Phone 7 application can be found here.

Sync I/O pauses the UI

The code below shows how ExecuteWithSyncIO method is implemented. The application shows a MessageBox to the user that the UI will pause while the execution is in progress.

private void ExecuteWithSyncIO()
{
    for (int n = 0; n < iterations; n++)
    {
        this.webService.GetStockQuotes();
    }
    SetStatus("Sync/IO completed.", StatusState.Ready);
}

Delegate's BeginInvoke method is not supported

private void ExecuteWithDelegateBeginInvoke()
{
    Func<IStockQuote> stockQuoteDelegate = this.webService.GetStockQuotes;
    // NOTE: Calling delegates asynchronously is NOT supported in WP7.
    stockQuoteDelegate.BeginInvoke((ar) =>
    {
        stockQuoteDelegate.EndInvoke(ar);        
    }, null);
}

The code below shows how ExecuteWithDelegateBeginInvoke method is implemented.

This method is here just for the demo, since it is not allowed to invoke a delegate asynchronously in the Compact Framework.

private void ExecuteWithDelegateBeginInvoke()
{
    Func<IStockQuote> stockQuoteDelegate = this.webService.GetStockQuotes;
    // NOTE: Calling delegates asynchronously is NOT supported in WP7.
    stockQuoteDelegate.BeginInvoke((ar) =>
    {
        stockQuoteDelegate.EndInvoke(ar);        
    }, null);
}

IAsyncResult interface

The code below shows how the ExecuteWithIAsyncResult method is implemented. The only problem is that, when using the IAsyncResult, you need to specify a method to be called when a corresponding asynchronous operation completes. This can result in using synchronization constructs to avoid race conditions. It also splits the flow of your code. You can inline the callback method using Anonymous Methods or Lamda Expressions as shown below but if your logic is complicated your code will not be beautiful.

private void ExecuteWithIAsyncResult()
{
    SetStatus("Working..", StatusState.Busy);

    for (int n = 0; n < iterations; n++)
    {
        this.webService.BeginGetStockQuotes((ar) =>
        {
            // Callback method inlined using Lamda Expressions.

            // NOTE: Code can become ugly here, specially if you need to do 
            // a lot of stuff that touch properties bounded with UI elements.
            if (Interlocked.Increment(ref this.numDone) == iterations)
            {
                Execute.OnUIThread(() =>
                {
                    SetStatus("IAsyncResult APM completed.",
                        StatusState.Ready);
                });
            }
        }, null);
    }
}

AsyncEnumerator class

The code below shows how ExecuteWithAsyncEnumerator method is implemented. As you can see this method makes your code looks like it's executing synchronously but actually it executes asynchronously. You do not have to split your code in callback methods or inlined delegates. You do not need to marshall calls in the UI thread using the Dispacher or the SynchronizationContext. All this stuff is handled by the AsyncEnumerator class.

private IEnumerator<int> ExecuteWithAsyncEnumerator(AsyncEnumerator ae)
{
    for (int n = 0; n < iterations; n++)
    {
        this.webService.BeginGetStockQuotes(ae.End(), null);
    }

    // AsyncEnumerator captures the calling thread's SynchronizationContext.
    // Set the Wintellect.Threading.AsyncProgModel.SynchronizationContext to
    // null so that the callback continues on a ThreadPool thread.
    ae.SyncContext = null;
    yield return iterations;

    for (int n = 0; n < iterations; n++)
    {
        this.webService.EndGetStockQuotes(ae.DequeueAsyncResult());
    }

    // AsyncEnumerator captures the synchronization context.
    SetStatus("AsyncEnumerator completed.", StatusState.Ready);
}

While what I've discussed in this post applies to Mobile application development, the same principles can be applied to Rich Internet applications and Smart client. I have been using the AsyncEnumerator class for over two years and I have to say that it changed the way I think about using the APM. At the end.. delivering responsive applications makes the end-users happy.