1

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?

4
  • 1
    Just wrap the blocking call in a delegate and use its async mechanism. Commented Feb 11, 2013 at 16:08
  • You will have to change the signature of your static method. You'll either need to return an object which will indicate when the operation is done and contain the result (i.e. IAsyncResult`), pass in a callback delegate, expose a static event, or something else. You won't be able to expose the string directly though unless you block, in which case it's not async. Commented Feb 11, 2013 at 16:29
  • @Servy can you show some code referring to what you mean? If this is what it sounds like, I'd like to give you credit for the answer. Commented Feb 11, 2013 at 18:06
  • @BillJones Which you use is likely dependant on the method used by the underlying async method. If it calls a callback then just pass your callback method to the async method. If it fires an event add an event handler to that event, and if it returns an object that exposes the async result in some manor, such as IAsyncResult, then return that. Commented Feb 11, 2013 at 18:19

2 Answers 2

1

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
Sign up to request clarification or add additional context in comments.

Comments

0

Create a class wrapping your service calls. From that only call the static blocking method, but call it from a background thread. Then execute a callback or raise an event once the service call returned:

public class CompletedEventArgs : EventArgs
{
    public string Result { get; set; }
}

public class MyServiceWrapper
{
    public event EventHandler<CompletedEventArgs> CallCompleted;

    public string SendData()
    {
        return StaticService.SendData();
    }

    public void SendDataAsync()
    {
        ThreadPool.QueueUserWorkItem(state => {
            var result = StaticService.SendData();
            var handler = CallCompleted;
            if (handler != null)
            {
                handler(this, new CompletedEventArgs{ Result = result });
            }
        });
    }
}

Keep in mind though that the event that gets raised does not come from the UI-thread, thus you have to dispatch it accordingly when you want to react to it in a UI.

2 Comments

I was suggesting a way more elegant method that this! See Delegate.BeginInvoke and Delegate.EndInvoke.
@leppie Sorry, then I understood you wrong (removed reference to your comment)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.