-2

I have two methods which return independent data. I assume it's a good idea to run them in parallel. Without any modifications code look's like:

private async Task<Entity> MethodAsync()
{
    ...
    var model1 = await client.Method1(Id1, cancellationToken);            
    var model2 = await client.Method2(Id2, cancellationToken);
    ...
}

Those methods return data as I expecting. Now when I change code all methods return "null". When I inspect Task object in visual studio there are properties Id = 2356, Status = RanToCompletion, Method = "{null}", Result = "".

private async Task<Entity> MethodAsync()
{
     var model1Task = client.Method1(Id1, cancellationToken);
     var model2Task = client.Method2(Id2, cancellationToken);
     var task = Task.WhenAll(new Task[] { model1Task ,model2Task });         
     await task;     //doesn't work
     //task.Wait();  //doesn't work
     //await Task.WhenAll(new Task[] { model1Task , model2Task }); //doesn't work
     //Task.WhenAll(new Task[] { model1Task, model2Task}); //doesn't work
}

Code of client methods almost the same:

public async Task<Model> Method1(Guid Id, CancellationToken cancellationToken)
{
    HttpResponseMessage responseMessage = await client.GetAsync($"customEndPoint");
    ResponseMessageSingle<Model> response = JsonSerializer.Deserialize<ResponseMessageSingle<Model>>(
        await responseMessage.Content.ReadAsStringAsync(cancellationToken),
        new JsonSerializerOptions(JsonSerializerDefaults.Web));

    return response.result;
}       

private class ResponseMessageSingle<T>
{
    public bool success { get; set; }
    public string message { get; set; }
    public T result { get; set; }
}

Also there is AuthorizeInterceptor(DelegatingHandler):

protected override async Task<HttpResponseMessage> SendAsync(
          HttpRequestMessage request, CancellationToken cancellationToken)
 {
      some logic...
      request.SetBearerToken(TokenResponse.AccessToken);
      HttpResponseMessage response = await base.SendAsync(request, cancellationToken);    
      return await Task.FromResult(response);
 }
Theodor Zoulias
  • 34,835
  • 7
  • 69
  • 104
TryHard
  • 125
  • 9
  • 5
    What does "doesn't work" mean? Exception? what exception? something else? The simplest explanation is that the code is not thread safe, and it throws an exception when run in parallel. – JonasH Oct 12 '22 at 11:39
  • 1
    "doesn't work" is not a sufficient error description. Do you get a compiling error? Or unexpected behaviour (like an exception or wrong values)? – SomeBody Oct 12 '22 at 11:40
  • After you await `Task.WhenAll` you need to get the results from the original tasks. `var model1 = await model1Task;` – juharr Oct 12 '22 at 11:41
  • I guess "doesn't work" equals to "throws a NullReferenceException"? – ˈvɔlə Oct 12 '22 at 11:43

1 Answers1

2

Task.WhenAll does not return a result in your case, because you create an array of Task, which has no result. And since your tasks return different results, you cannot get that in an array nicely.

You should change your code like this to get the results of your methods:

private async Task<Entity> MethodAsync()
{
    var model1Task = client.Method1(Id1, cancellationToken);
    var model2Task = client.Method2(Id2, cancellationToken);
    var task = Task.WhenAll(new Task[] { model1Task ,model2Task });         
    await task;
    var result1 = await model1Task;
    var result2 = await model2Task;
    ...
 }

Since both methods will be completed, awaiting them will just immediately get you the results.

Nick
  • 4,787
  • 2
  • 18
  • 24