1

我无法找到这个问题的答案。请帮忙。
方案
我可以使用 Task.WhenAll 一次等待多个任务。但我希望它在一个策略断路器execution方法中。下面是代码片段。我正在调用 API 2 次,并希望一次获取调用结果。如果没有断路器,它就可以工作,我可以稍后在我的代码中使用结果。但我不明白如何使用Task.WhenAll内部断路器调用 API。

var param1 = new Param
{
    Category = Category.Manager,
    FirstName = "John",
    Address = "Sydney",
};
var param2 = new Param
{
    Category = Category.Officer,
    FirstName = "Adam",
    Address = "Melbourne",
};

工作代码:

var results1 = Task.WhenAll(_apiClient.GetAsync(param1), _apiClient.GetAsync(param2));
//At this point results1 is NOT null and contains 2 items in it

问题:

var results2 = _policyCircuitBreaker.Execute(()=> Task.WhenAll(_apiClient.GetAsync(param1), _apiClient.GetAsync(param2)));
//at this point results2 is of type Task, how can I get the results2 similar to results1
4

2 回答 2

2

一般来说,正如 Johnathon Sullinger 所说,如果你有 aTask<TResult>并且想以Task非阻塞方式获得结果,那么await-ing Task<TResult>(或使用延续)是要走的路。

但是,假设您的断路器来自Polly,原始问题的公式(在下面重复)不会给出您可能想要的异步断路器行为:

var results = _policyCircuitBreaker.Execute(() => Task.WhenAll(param1Task, param2Task));

该公式使用同步.Execute(...):因此,.Execute(...)调用_policyCircuitBreaker将仅Task.WhenAll(...) 同步(近乎立即)控制,返回 Task<[]>表示等待内部任务完成的。断路器将不会(在此公式中)管理您对_apiClient.GetAsync(...).

假设您的意图是断路器应该管理调用_apiClient.GetAsync(param1)_apiClient.GetAsync(param2)(即响应这些调用可能引发的故障),您需要使用 Polly 的异步原生策略和.ExecuteAsync()重载:

var results3 = await _policyCircuitBreaker.ExecuteAsync(() => Task.WhenAll(_apiClient.GetAsync(param1), _apiClient.GetAsync(param2))));

.ExecuteAsync(...)在将策略行为(在本例中为断路器行为)应用于它时,在内部等待您提供的委托。

于 2017-03-14T09:10:08.140 回答
0

您需要在_policyCircuitBreaker呼叫之外存储对任务的引用。

var param1Task = _apiClient.GetAsync(param1);
var param2Task = _apiClient.GetAsync(param2);

Task results = _policyCircuitBreaker.Execute(() => Task.WhenAll(param1Task, param2Task));

要么等待断路器调用,要么在完成时使用延续来获取结果。

等待示例:

await results;
var param1ApiResult = param1Task.Result;
var param2ApiResult = param2Task.Result;

继续示例(对于无法等待的代码路径)

results.ContinueWith(finishedTask =>
{
    var param1ApiResult = param1Task.Result; 
    var param2ApiResult = param2Task.Result;
});

这两个示例都会为您提供结果 - 您只需要在调用中执行它们之前存储对每个任务的引用WhenAll。这样一来,您就可以在Tasks完成后获得他们的结果。

我做出了一些假设,因为您的帖子不清楚您尝试使用的 API 以及 Execute 方法 API 的外观。

于 2017-03-14T04:37:41.387 回答