Wrap a function as an async task

2019-07-11 07:42发布

问题:

I have a function that I would like to wrap so that I can use the async/await pattern:

wcfClientService.GetSomeString(parameter);

It's a call from a WCF client that I'm trying to make asynchronous, but that's not important (I know WCF supports async, but let's assume we don't have access to the WCF code).

I'm trying to wrap the method with the Task<T>.Factory.FromAsync method, but can't seem to get it right:

private Task<string> WrapWcfServiceAsyncTask(uint parameter)
{
    Func<uint, string> func = i => { return wcfClientService.GetSomeString(parameter); };

    var t = Task<string>.Factory.FromAsync(
                                           // What goes here?
                                          );
    return t;
}

Or even better, can someone write a method that takes a method as a parameter, and wraps and returns a Task<T> for it?

回答1:

What you're trying to do is async over sync. You have a synchronous operation and you want to pretend it's asynchronous .

You can do that with Task.Run:

var result = await Task.Run(() => wcfClientService.GetSomeString(parameter));

but it's pointless as you're just offloading work from one ThreadPool thread to another.

If you want an asynchronous operation it needs to be asynchronous to begin with in some way, either with async-await or Begin/End, etc.

If you had BeginGetSomeString/EndSomeString which is already asynchronous you could have used FromAsync to turn it into async-await.



回答2:

If you re-generate your WCF proxy with a modern version of Visual Studio, it should generate task-returning asynchronous methods by default. Note that the WCF service does not have to change at all; it is only the client proxy that needs to be updated.

Then you can call its methods with a plain await; there's no need for Task.Run:

private async Task<string> WrapWcfServiceAsyncTask(uint parameter)
{
  return await wcfClientService.GetSomeStringAsync(parameter);
}