8

我想将 TPL 与现有的 API 一起使用,具体来说就是 RestSharp,所以我可以使用延续。

但这意味着我必须包装一个不采用经典 .NET 异步方法的 API,而是实现回调。采取一些这样的代码:

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

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

因此,如果可能的话,我想在这里将 ExecuteAsync 包装在 TPL 中。但我不能为我的生活,弄清楚如何去做。

有任何想法吗?

4

2 回答 2

12

TPL 提供了TaskCompletionSource类,它允许您将几乎任何东西公开为任务。通过调用SetResultSetException,您可以使任务成功或失败。在您的示例中,您可能可以执行以下操作:

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;
}

然后你可以使用它:

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

或者,如果您想链接任务:

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

您可以在http://blogs.msdn.com/b/pfxteam/archive/2009/06/02/9685804.aspx阅读有关 TaskCompletionSource 的更多信息

于 2011-08-09T01:49:50.700 回答
1

这也是我学习 TPL 时的一个主要痛点。

您正在寻找的是TaskCompletionSource. 当您创建 aTaskCompletionSource时,它会创建一个特殊Task对象(可由TaskCompletionSource.Task属性访问),该对象仅在您调用关联的SetResultSetException方法时完成TaskCompletionSource

这篇文章解释了如何使用 TPL(以及 Rx)封装 APM 操作。另请参阅此要点,演示包装在 TPL 中的 APM 操作。

于 2011-08-09T16:30:51.050 回答