Using new async invocation pattern in ASP.NET Web Services

My colleague Dennis just asked me how you would asynchronously invoke web services (in VB.NET).


The new way


As Dennis already figured out there is a new way to do this in ASP.NET 2.0. In fact, the new way is all over the .NET Framework 2.0 and is referred to as the event-based asynchronous pattern. There are a few important differences with the old way in .NET 1.0 and 1.1. First, let’s set up a sample for an ASP.NET web service.



Public Class VentriloService


    Inherits System.Web.Services.WebService


 


  <WebMethod()> _


  Public Function Listen() As Byte()


    Return Nothing


  End Function


 


End Class


There is a single method called listen in the web service. Another project adds a Web Reference to this webservice (or uses wsdl.exe) and will generate code containing the following:




  • The usual proxy class (VentriloService), but with Listen method, ListenAsync overloads, a ListenCompleted event and a CancelAsync method
  • Specialized event arguments for the ListenCompleted event (ListenCompletedEventArgs)
  • A delegate definition for the signature of the ListenCompleted event (ListenCompletedEventHandler)

You can use the asynchronous version of Listen like this:



Imports VentriloLibrary.localhost


 


Public Class VentriloClient


 


  Public Sub StartListening()


    Dim service As New localhost.VentriloService


    AddHandler service.ListenCompleted, AddressOf ListenCompleted


    service.ListenAsync(Guid.NewGuid())


 


    If SomeCondition = True Then


      service.CancelAsync(Nothing)


    End If


  End Sub


 


  Private Sub ListenCompleted(ByVal sender As Object, ByVal e As ListenCompletedEventArgs)


    If Not e.Cancelled Then


      Console.WriteLine(“Call with ID {0} finished with result {1}”, e.UserState, e.Result)


    End If


  End Sub


End Class


First, look in the StartListening method. It instantiates a proxy object and registers an event handler for the ListenCompleted event. Pretty easy. Next, it starts the async operation by calling ListenAsync. There are two overloads, one of which takes an UserState argument. More on that in a moment.
Once the asynchronous operation completes, the ListenCompleted event is fired and it will trigger all registered event handlers. Before that time you can cancel all pending async operations by calling CancelAsync.


The UserState that you can pass along to ListenAsync can be any object that you find necessary to correlate this call (it runs on a new thread) inside of the event handler. You could potentially start off multiple async calls with the same event handler, that come back in an arbitrary order. The completed calls can be distinguished by the UserState object that you passed along.


If you want to, you can even go the extra VB mile and use WithEvents to skip the AddHandler call:



Public Class VentriloClient


 


  Dim WithEvents service As New localhost.VentriloService


 


  Public Sub StartListening()


    service.ListenAsync(Guid.NewGuid())


  End Sub


 


  Private Sub ListenCompleted(ByVal sender As Object, ByVal e As ListenCompletedEventArgs) Handles service.ListenCompleted


  End Sub


End Class


The old way


Let me also show you the old fashioned way for contrast. Check this code.



Imports VentriloLibrary.localhost


 


Public Class VentriloClient


  Public Sub StartListening()


    Dim service As New VentriloService


    Dim callback As New AsyncCallback(AddressOf ListenCallback)


    Dim asyncResult As IAsyncResult


    asyncResult = service.BeginListen(callback, Guid.NewGuid())


  End Sub


 


  Public Sub ListenCallback(ByVal ar As IAsyncResult)


    Dim service As New VentriloService


    Dim result As Byte() = service.EndListen(ar)


 


    Console.WriteLine(“Call with ID {0} finished with result {1}”, _


    DirectCast(ar.AsyncState, Guid), result)


  End Sub


End Class


You can clearly see that you are confronted with lots more of the nitty, gritty details of the asynchronous invocation, including the invocation of the EndListen method. Admitted, this could give you a little more control.


Summary


In summary, the event-based asynchronous pattern is



  • New in .NET Framework 2.0
  • Easier to use than the old pattern
  • Better for control over cancellation of async thread
  • Less useful if you want to poll or make a blocking finish call.
  • More intuitive to add multiple handlers (by calling AddHandler or += (for C#) multiple times)

Dutch readers might want to look at my Visual Basic Group article on delegates from way back. 

Advertisements
This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s