April 2004 - Posts

Whidbey Tech Preview breaks Reporting Services

 Just a warning:  Installing the latest Whidbey Tech Preview will break an installation of Reporting Services.

Has anyone found a way to fix it?

Another Asynchronous call pattern for Web Services

 I came across the following link the other day.  It talks about simplifies the way that you call web services and takes care of making sure asynchronous callbacks happen on the UI thread.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwinforms/html/SACP_WinForms.asp

I have often made use of a different pattern that involves less code and I think is pretty elegant.  Here is an example of the code:

private void LoadAllPatients()
{
      WebService ws = new WebService();
 
      // Call the web service, pass the instance
      ws.BeginGetPatients(
            “Ward1”,                            // Parameter for the GetPatients method
            new AsyncCallback(OnGetPatients),   // Callback delegate
            ws );                               // Instance of the web service that is used in the callback method
}
 
private void OnGetPatients( IAsyncResult result )
{
      // Make sure this method gets called from the UI thread
      if ( this.InvokeRequired )
      {
            this.Invoke( new AsyncCallback(OnGetPatients), new object[] { result } );
            return;
      }
 
      // Get the web service instance from the callback result
      WebService ws = (WebService)result.AsyncState;
      try
      {
            // Get the results from the web method
            Patient[] patients =ws.EndGetPatients( result );
 
            // Do some stuff with the patient array that involves UI controls
      }
      finally
      {
            // Get rid of the web service instance
            ws.Dispose();
      }
}

Some notes:

1)      Since the web service callback is already using a delegate (AsyncCallback), why not use it for the Invoke call?  That keeps you from having to create a new specialized delegate like ‘delegate void UpdatePatientsHandler( Patient[] )’ every time you need to use Invoke.

2)      Looking at the web service proxy code, it looks like I should have a new instance for every call that I am making if I think that I might have several calls in progress at the same time.  Instead of having one web service instance for the window object, I create a new instance with each call and pass it along with the web service call.  The callback method can extract it from the IAsyncResult interface.

3)      Wrap the EndGetPatients call with a try/finally block to make sure that the webservice instance is disposed.

The solution that David Hill has come up with does make for a very easy bit of programming for the UI coder and is a good solution when you are trying to develop a solution that will be handed off to other developers.  But I think my solution is quicker to develop.