Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrap a function as an async task

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?

like image 746
Drake Avatar asked Dec 15 '22 11:12

Drake


2 Answers

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.

like image 148
i3arnon Avatar answered Dec 17 '22 00:12

i3arnon


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);
}
like image 30
Stephen Cleary Avatar answered Dec 17 '22 00:12

Stephen Cleary