In addition to making synchronous calls via the Invoke method on proxy classes derived from XmlRpcClientProtocol, it is possible to make asynchronous calls via the BeginInvoke and EndInvoke methods of XmlRpcClientProtocol. Broadly speaking there are two ways of processing asynchronous calls: by polling to determine when the call has completed, and by supplying a delegate to receive a callback when the call has completed.
Asynchronous calls will be illustrated with this example proxy class:
public struct Result
{
public int sum;
public int difference;
}
[XmlRpcUrl("http://saturn/xmlrpc/sumanddiffvb.aspx")]
class SumAndDiffProxy : XmlRpcClientProtocol
{
public
IAsyncResult BeginSumAndDifference(
int
x, int y,
AsyncCallback callback, object asyncState)
{
return BeginInvoke("SumAndDifference",
new object[]{x, y},
callback, asyncState);
}
public
Result EndSumAndDifference(IAsyncResult asr)
{
return (Result)EndInvoke(asr)[0];
}
}
The BeginSumAndDifference method of SumAndDiffProxy takes 4 parameters: the two numbers to be processed, an AsyncCallback delegate, and an object which can be used to store some state across the call (not used in the examples on this page). It returns an instance of the IAsyncResult interface, which is passed into the EndSumAndDifference method to retrieve the result of the call.
The last two parameters of BeginSumAndDifference are not required and can be passed as null. So the asynchronous call would begin like this:
IAsyncResult asr = theProxy.BeginSumAndDifference(5, 3, null, null);
An instance of the IAsyncResult is returned. This has several public properties, the interesting one for polling being the boolean property IsCompleted. The value of this property can be checked as required until is found to be true, for example:
while (true)
{
if (asr.IsCompleted)
break;
Thread.Sleep(1000);
}
Once the call has completed the result of the call can be obtained by calling EndSumAndDifference, passing in the instance of IAsyncResult returned from the call to BeginSumAndDifference:
try
{
Result ret = theProxy.EndSumAndDifference(asr);
}
catch(Exception ex)
{
// handle the exception
}
Note that a try-catch block is placed around the call to EndSumAndDifference. This is because any exceptions thrown during the asynchronous processing of the call, for example a network error, are stored until the XmlRpcClientProtocol method EndInvoke is called, at which point the the exception is rethrown.
When a callback approach is used, a method must be defined and used with a delegate to take the callback:
static void SumAndDiffCallback(IAsyncResult
asr)
{
try
{
SumAndDiffProxy theProxy = (SumAndDiffProxy)ar.AsyncObject;
Result ret = theProxy.EndSumAndDifference(asr);
}
catch(Exception ex)
{
// handle the exception
}
}
This time when calling BeginSumAndDifference an AsyncCallback delegete must be created and passed into the call:
AsyncCallback acb = new AsyncCallback(SumAndDiffCallback);
theProxy.BeginSumAndDifference(5, 3, acb, null);
The IAsyncResult returned from the call is ignored because all further handling of the call is done via the callback.
When the call is completed, the callback method is called and the original SumAndDiffProxy used to make the call can be retrieved from the AsyncObject property of the IAsyncResult interface. EndSumAndDifference can then be called to retrieve the result.
| © Charles Cook, 2001 All Rights Reserved. |
14
May 2001
|