Search code examples
c#asynchronous.net-2.0

Asynchronous call with a static method in C# .NET 2.0


I have a .NET 2.0 application. In this application, I need to pass data back to my server. The server exposes a REST-based URL that I can POST data to. When I pass data back to my server, I need to sometimes do so asynchronously, and other times I need a blocking call. In the scenario of the asynchronous call, I need to know when the call is completed. Everything up to this point I understand how to do.

Where I get into trouble is, the method that I am working on MUST be static. It's code I've inherited, and I'd rather not have to redo all of this code. Currently, I have two static methods:

public static string SendData (...) {
}

public static string SendDataAsync(...) {

}

The string returned is a response code from the server. The static part is giving me fits. It doesn't cause a problem in my blocking version. However, in the contest of the asynchronous call, I'm not sure what to do.

Does anyone have any insights they can provide?


Solution

  • This is the general async pattern before C# 5 (IIRC).

    public static string SendData (...) {
    }
    
    public static IAsyncResult BeginSendData(..., AsyncCallback cb) {
       var f = new Func<..., string>(SendData);
       return f.BeginInvoke(..., cb, f);
    }
    
    public static string EndSendData(IAsyncResult ar) {
       return ((Func<..., string>) ar.AsyncState).EndInvoke(ar); 
    }
    

    Usage:

    BeginSendData(..., ar => 
       {
         var result = EndSendData(ar);
         // do something with result
       });
    

    Full console example:

    public static string SendData(int i)
    {
        // sample payload
        Thread.Sleep(i);
        return i.ToString();
    }
    
    public static IAsyncResult BeginSendData(int i, AsyncCallback cb)
    {
        var f = new Func<int, string>(SendData);
        return f.BeginInvoke(i, cb, f);
    }
    
    public static string EndSendData(IAsyncResult ar)
    {
        return ((Func<int, string>)ar.AsyncState).EndInvoke(ar);
    }
    
    static void Main(string[] args)
    {
        BeginSendData(2000, ar => 
            {
                var result = EndSendData(ar);
                Console.WriteLine("Done: {0}", result);
            });
    
        Console.WriteLine("Waiting");
        Console.ReadLine();
    }
    

    The above will print:

    Waiting
    Done: 2000