如何在 C# 中的策略断路器中同时等待多个任务?

How can I await multiple tasks at the same time inside policy circuit breaker in c#?

我找不到这个问题的答案。请帮忙。
场景
我可以使用 Task.WhenAll 一次等待多个任务。但我希望它在策略断路器 execution 方法中。下面是代码片段。我打了 2 次 API 并且想一次获得通话结果。在没有断路器的情况下,它可以正常工作,我可以稍后在我的代码中使用结果。但是我不明白如何在断路器内部使用 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

您需要在 _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 完成后获得他们的结果。

我正在做一些假设,因为您的 post 不清楚您尝试使用的 API 以及执行方法 API 的样子。

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

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

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

该公式使用同步 .Execute(...):因此,通过 _policyCircuitBreaker.Execute(...) 调用将仅控制 Task.WhenAll(...) 同步 ( near-immediately) 返回 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(...) 在内部等待您提供的委托,同时对其应用策略行为(在本例中为断路器行为)。