Claus Jørgensen
Claus Jørgensen

Reputation: 26336

Using TPL with existing async APIs

I want to use TPL with a existing API, RestSharp to be specific, so I can use continuations.

But this means I have to wrap a API that doesn't take the classical .NET approach to async, but instead implements callbacks. Take some code like this:

var client = new RestClient("service-url");
var request = new RestRequest();

client.ExecuteAsync<List<LiveTileWeatherResponse>>(request, 
    (response) =>
    {
        ...
    });

So here I want to wrap the ExecuteAsync in TPL, if it's possible. But I can't for the life of me, figure out how to do it.

Any ideas?

Upvotes: 8

Views: 1378

Answers (2)

bvanderveen
bvanderveen

Reputation: 763

This was a major pain point for me when learning the TPL as well.

What you're looking for is TaskCompletionSource. When you create a TaskCompletionSource, it creates a special Task object (accessible by the TaskCompletionSource.Task property) which only completes when you call the SetResult or SetException methods on the associated TaskCompletionSource.

This post explains how to wrap APM operations with the TPL (and also Rx). See also this gist demonstrating an APM operation wrapped in the TPL.

Upvotes: 1

Bojan Resnik
Bojan Resnik

Reputation: 7388

TPL provides TaskCompletionSource class which allows you to expose pretty much anything as a Task. By calling SetResult or SetException, you can cause the task to succeed or fail. In your example, you could probably do something like:

static Task<T> ExecuteTask<T>(this RestClient client, RestRequest request)
{
    var tcs = new TaskCompletionSource<T>();
    client.ExecuteAsync<T>(request, response => tcs.SetResult(response));
    return tcs.Task;
}

You can then use it:

var task = client.ExecuteTask<List<LiveTileWeatherResponse>>(request);
foreach (var tile in task.Result)
{}

Or, if you want to chain tasks:

var task = client.ExecuteTask<List<LiveTileWeatherResponse>>(request);
task.ContinueWith(
    t => 
    {
        foreach (var tile in t.Result)
        {}
    }
);

You can read more about TaskCompletionSource at http://blogs.msdn.com/b/pfxteam/archive/2009/06/02/9685804.aspx

Upvotes: 12

Related Questions