posted on Friday, April 02, 2004 1:11 PM
by
robcannonsoftware
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.