118 Chapter 4: Beyond the Basics
■
method for the callback:
AsyncCallback ac = new AsyncCallback(myMethodToCall);
:
:
:
public static void myMethodToCall(IAsyncResult result) {
// callback code goes here
}
If no callback method is required, this argument can be null (although remember that
the end method must be invoked somewhere). The callback method itself must have the
signature public static void <callbackMethodName>(IAsyncResult). The IAsyncResult
class will be discussed in a moment.
The object argument is simply a way to convey user-defined information from the
caller to the callback. This information could be the NetworkStream or socket class instance
itself, or a user-defined class that includes both the NetworkStream, the byte buffer being
used, and anything else to which the application callback method needs access.
The BeginRead() and BeginWrite() methods also have a different return type: an
IAsyncResult instance. The IAsyncResult represents the status of the asynchronous
operation and can be used to poll or block on the return of that operation. If you decide
to block waiting for the operation to complete, the IAsyncResult’s AsyncWaitHandle
property contains a method called WaitOne(). Invoking this method will block until the
corresponding end method is called.
Once the asynchronous operation completes, the callback method is invoked. The
callback method receives an IAsyncResult instance as an argument, which has a property
called AsyncState that will contain an object. This object is the same object that was
passed to the begin method, and needs to be cast to its original type before being used.
The IAsyncResult instance is also used as the argument to the end call. The end call
completes the symmetry of the call and returns the result of the call. That result is the
exact same value that the synchronous version of the call would have returned.
public override int EndRead(IAsyncResult asyncResult);
public override void EndWrite(IAsyncResult asyncResult);
As an example let’s assume that BeginRead() is called on a NetworkStream instance,
and in addition to the usual arguments passed a callback method (new AsyncCall-
back(myCallback)) and the read byte buffer as the state. The EndRead() call will return
the number of bytes read from the NetworkStream, the same as a synchronous call to
Read() would have.
public static void myCallback(IAsyncResult result) {
byte[] buffer = (byte[])result.AsyncState;
int bytesRead = EndRead(result);
Console.WriteLine("Got {0} bytes of: {1}", bytesread, buffer);
}