Using TPL with Existing Asynchronous APIs

I want to use TPL with an existing API, RestSharp, to be specific, so I can use extensions.

But that means that I need to wrap an API that does not use the classic .NET approach for async, but instead performs callbacks. Take some code:

var client = new RestClient("service-url"); var request = new RestRequest(); client.ExecuteAsync<List<LiveTileWeatherResponse>>(request, (response) => { ... }); 

So here I want to wrap ExecuteAsync in TPL, if possible. But I cannot for the life of me figure out how to do this.

Any ideas?

+8
c # task-parallel-library restsharp
source share
2 answers

TPL provides the TaskCompletionSource class, which allows you to display almost anything as a task. By calling SetResult or SetException , you can make the task succeed or fail. In your example, you could 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; } 

Then you can use it:

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

Or if you want to link tasks:

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

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

+12
source share

This was a serious problem for me when learning TPL.

What you are looking for is TaskCompletionSource . When you create a TaskCompletionSource , it creates a special Task object (accessible by the TaskCompletionSource.Task property), which terminates only when the SetResult or SetException methods SetResult SetException in the corresponding TaskCompletionSource .

This post explains how to transfer APM operations using TPL (as well as Rx). See Also this method for an APM operation wrapped in a TPL.

+1
source share

All Articles