问题
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?
回答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
回答2:
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.
来源:https://stackoverflow.com/questions/14815984/asynchronous-call-with-a-static-method-in-c-sharp-net-2-0