How to use async-await with WCF in VS 2010 for WP7

2019-04-15 06:30发布

问题:

Async CTP is very nice to use. I saw some examples for windows phone, all using:
(Assembly AsyncCtpLibrary_Phone.dll, v2.0.50727, AsyncCtpExtensions).

 var client = new WebClient();
 string data = await client.DownloadStringTaskAsync(new Uri(url));

or something like the above code.

How can I use methods with async / await for my services? (WCF)
Today all methods work this way:

  service.MyRequestCompleted += service_myRequestCompleted;
  service.MyRequestAsync();

I can not find a way to use extension methods for services.

回答1:

Unfortunetly, I haven't found a good way to generalize this for any event, but it's easy enough to adapt this for a particular event:

public static Task WhenRequestCompleted(MyService service) //can make it an extension method if you want.
{
    TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();

    service.MyRequestCompleted += () => //change parameter list to fit the event's delegate
        {
            tcs.SetResult(null);
        };
    service.MyRequestAsync();

    return tcs.Task;
}

Then you can do:

await WhenRequestCompleted(service);
//code that runs after the request is completed.

I assume you see the pattern here, so you could adapt this so that it would work with some other event on some other type.

Oh, and if the event has arguments that are particularly important to you then you could make this return a Task<T> instead of a Task and instead of using tcs.SetResult(null) you could use one of the parameters of the lambda to set the result.



回答2:

It's been a while since I've worked on WP7, so I'm going to assume that the client proxy has both EAP endpoints (*Async + *Completed) and APM endpoints (Begin* + End*) for each contract method.

If that's correct, then you can use TaskFactory.FromAsync to wrap the Begin* / End* methods, as such:

[ServiceContract]
public interface ICalculator
{
  [OperationContract]
  uint Divide(uint numerator, uint denominator);
}

static class Program
{
  // Wrap those Begin/End methods into a Task-based API.
  public static Task<uint> DivideAsyncTask(this CalculatorClient client,
      uint numerator, uint denominator)
  {
    return Task<uint>.Factory.FromAsync(client.BeginDivide, client.EndDivide,
        numerator, denominator, null);
  }

  static async Task CallCalculator()
  {
    var proxy = new CalculatorClient();
    var task = proxy.DivideAsyncTask(10, 5);
    var result = await task;
    Console.WriteLine("Result: " + result);
  }

  static void Main(string[] args)
  {
    try
    {
      CallCalculator().Wait();
    }
    catch (Exception ex)
    {
      Console.Error.WriteLine(ex);
    }

    Console.ReadKey();
  }
}

You may be interested in one of my blog posts async WCF today and tomorrow - unfortunately, WP7 is still stuck in "today" mode. The Async CTP will probably be abandoned shortly now that VS2012 is out.