NGWS SDK Documentation  

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

ASP+ Web Services Async Support

ASP+ WebServices supports both a synchronous and asynchronous execution model. Synchronous execution is conceptually much simpler to understand; it works just like a normal method call in a class. Asynchronous execution, however, can potentially provide much better server utilization and system throughput when used with code that performs blocking operations, such as reading from the filesystem, executing a query against SQL Server, or other lengthy operations.

Developers write asynchronous code within an ASP+ Web Service by splitting the web- callable methods into two separate routines: one method that executes at the beginning of the request and executes up to an asynchronous operation (that would otherwise block), and the other method that is called once the asynchronous operation completes and normal execution can continue. The two methods a developer writes follow the naming pattern (things in bold+italic are customizable by the webmethod developer):

Begin Method:

   IAsyncResult BeginMethodName(MethodArg arg1-argN, AsyncCallback callback, object state);

End Method:

   ReturnArg EndMethodName(IAsyncResult result);

The resulting webmethod signature exposed to clients would then look like:

    ReturnArg MethodName(MethodArg arg1-argN);

The below example demonstrates a webservice implemented using the async pattern that exposes a single method ReadData that asynchronously reads a file and transmits the bytes back to a client:

<%@ WebService Language=”C#” Class=”MyWebService“ %>

using System.Web.Services;
using System.IO;

public class MyWebService : WebService {

    [ WebMethod ]
    public IAsyncResult BeginReadData(string dataID, AsyncCallback callback, object state) {

        File file = new File(dataID);
        Stream stream = file.Open(FileMode.Open, FileAccess.Read, FileShare.Read);       
        byte[] bytes = new byte[(int)stream.Length];
        ReadDataAsyncState readState = new ReadDataAsyncState(callback, state, bytes);
        AsyncCallback readCallback = null;
        if (callback != null)
            readCallback = new AsyncCallback(ReadDataCallback);
        IAsyncResult result = stream.BeginRead(bytes, 0, bytes.Length, readCallback, readState);       
        return new ReadDataAsyncResult(callback, result, readState);
    }

    [WebMethod]
    public string EndReadData(IAsyncResult result) {

        ReadDataAsyncResult readAsyncResult = (ReadDataAsyncResult)result;
        IAsyncResult innerAsyncResult = readAsyncResult.InnerAsyncResult;
        Stream stream = (Stream)innerAsyncResult.AsyncObject;
        int count = stream.EndRead(innerAsyncResult);
        string s = Encoding.ASCII.GetString(readAsyncResult.readState.bytes, 0, count);
        return s;
    }

    private void ReadDataCallback(IAsyncResult result) {

        ReadDataAsyncState state = (ReadDataAsyncState) result.AsyncState;
        ReadDataAsyncResult readAsyncResult = new ReadDataAsyncResult(state.callerCallback,
                                                                                                            result, state);
        state.callerCallback(readAsyncResult);
    }
}

class ReadDataAsyncState {
 
    public ReadDataAsyncState(AsyncCallback callerCallback, object callerState, byte[] bytes) {

        this.callerState = callerState;
        this.callerCallback = callerCallback;
        this.bytes = bytes;
    }

    public object callerState;
    public AsyncCallback callerCallback;
    public byte[] bytes;   
}

class ReadDataAsyncResult : AsyncResult {

    public ReadDataAsyncState readState;
    public ReadDataAsyncResult( AsyncCallback callback,
                                               IAsyncResult result,
                                               ReadDataAsyncState readState) : base(callback, result) {

        this.readState = readState;
    }
}