Reputation: 938
I wasn't able to find an answer to this question. Please help.
Scenario
I can wait for multiple tasks at a time by using Task.WhenAll. But I want it inside a policy circuit breaker execution
method. Below is the code snippet. I am calling an API 2 times and wanted to get the call results at a time. Without circuit breaker, it is working, and I can use the results later in my code. But I do not understand how I can call the API using Task.WhenAll
inside circuit breaker.
var param1 = new Param
{
Category = Category.Manager,
FirstName = "John",
Address = "Sydney",
};
var param2 = new Param
{
Category = Category.Officer,
FirstName = "Adam",
Address = "Melbourne",
};
Working code:
var results1 = Task.WhenAll(_apiClient.GetAsync(param1), _apiClient.GetAsync(param2));
//At this point results1 is NOT null and contains 2 items in it
Problem:
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
Upvotes: 1
Views: 389
Reputation: 8156
In general, as Johnathon Sullinger says, if you have a Task<TResult>
and want to obtain the result of that Task
in a non-blocking way, await
-ing that Task<TResult>
(or using a continuation) is the way to go.
Assuming however your circuit-breaker is from Polly, the formulation from the original question (repeated below) will not give the async circuit-breaker behaviour you likely want:
var results = _policyCircuitBreaker.Execute(() => Task.WhenAll(param1Task, param2Task));
That formulation uses the synchronous .Execute(...)
: the .Execute(...)
call through _policyCircuitBreaker
will thus only govern Task.WhenAll(...)
synchronously (near-immediately) returning the Task<[]>
which represents waiting for the inner tasks to complete. The circuit-breaker will not (in this formulation) govern your calls to _apiClient.GetAsync(...)
.
Assuming your intention is that the circuit-breaker should govern both the calls _apiClient.GetAsync(param1)
and _apiClient.GetAsync(param2)
(ie respond to faults those calls may raise), you need to use Polly's async-native policies and .ExecuteAsync()
overloads:
var results3 = await _policyCircuitBreaker.ExecuteAsync(() => Task.WhenAll(_apiClient.GetAsync(param1), _apiClient.GetAsync(param2))));
.ExecuteAsync(...)
internally awaits the delegate you have supplied while applying the policy behaviour (in this case circuit-breaker behaviour) to it.
Upvotes: 2
Reputation: 7414
You will need to store a reference to the Tasks outside of your _policyCircuitBreaker
call.
var param1Task = _apiClient.GetAsync(param1);
var param2Task = _apiClient.GetAsync(param2);
Task results = _policyCircuitBreaker.Execute(() => Task.WhenAll(param1Task, param2Task));
Either await the circut breaker call, or use a continuation to get the results when they are completed.
await results;
var param1ApiResult = param1Task.Result;
var param2ApiResult = param2Task.Result;
results.ContinueWith(finishedTask =>
{
var param1ApiResult = param1Task.Result;
var param2ApiResult = param2Task.Result;
});
Both examples will give you the results - you just need to store a reference to each Task, before you execute them in the WhenAll
call. That lets you get their results later once the Tasks
have completed.
I'm making some assumptions because your post wasn't clear as to what API you are trying to use nor what the Execute methods API looks like.
Upvotes: 0