-1

by reading the following guide https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/async/ I was trying to create three tasks that should run async, concurrently, but they actually run synchrously. I'm wondering where I'm wrong

Task<double?[]> rainfallGridValuesTask = Rainfall.ValuesAsync(rainfallGridValuesRepo.GetAll());  //it takes 5s
Task<double?[]> rainfallAvgValuesTask = Rainfall.AveragesAsync(rainfallAvgGridValuesRepo.GetAll());  //it takes 5s
Task<double?[][]> rainfallAnomaliesTask = Rainfall.AnomaliesAsync(rainfallGridValuesRepo.GetAll());  //it takes 5s

where the methods are like the following:

public static async Task<double?[]> Values(IQueryable<RainfallGridValue> rainfallGridValues)
{
    double?[] outputValues = new double?[108];

    System.Threading.Thread.Sleep(5000);  //Simulate the time taken by the method
    return outputValues;
}

Then I try to get the value returned by the task in this way:

rainfallValueChart.Data = await rainfallGridValuesTask;
rainfallAverageChart.Data = await rainfallAvgValuesTask ;
rainfallAnomalyChart.Data = await rainfallAnomaliesTask ;

But when I run this code, it waits for 5s on each of the three Async methods, so what's wrong and how can I run them concurrently and proceed when all tasks have been completed?

Giox
  • 4,785
  • 8
  • 38
  • 81
  • 3
    Async methods are only async from the first call of "await". Replace `System.Threading.Thread.Sleep(5000);` with `await Task.Delay(5000);` – 230Daniel Feb 02 '21 at 21:51
  • Async is all about using a single thread more efficiently. It is *not* about concurrency and multi threaded applications. – TJ Rockefeller Feb 02 '21 at 21:52
  • 4
    Are these supposed to be performing 5 seconds of CPU-intensive computation? Then your simulation is pretty good and the observations are valid. Are they supposed to be performing 5 seconds of I/O? Then you should switch to `await Task.Delay` for your simulation. – Ben Voigt Feb 02 '21 at 21:52
  • @BenVoigt it's more related to I/O as they need to query a Remote DB with complex queries. So the implementation is correct, it's the way I'm simulating that is wrong? and the comment of TJRockefeller? – Giox Feb 02 '21 at 22:04
  • 1
    @Giox: As long as the actual methods are using `await` internally, you should simulate with `await Task.Delay()`. If they aren't using `await` internally, but some other async/overlapped system, like BeginXYZ/EndXYZ or callbacks, you can make a wrapper that's compatible with awaitable Tasks. – Ben Voigt Feb 02 '21 at 22:07
  • @BenVoigt let's simplify it saying that it's only a query on linq, how could I wrap it? – Giox Feb 02 '21 at 22:10
  • @Giox: If it's an SQL query (SELECT command), you would use `ExecuteReaderAsync` instead of `ExecuteReader`. LINQ can be used for all kinds of different backends, so your situation may vary. – Ben Voigt Feb 02 '21 at 22:11
  • 2
    Also, please don't ignore compiler warnings. There is a compiler warning that literally says `Values` will run synchronously. – Stephen Cleary Feb 03 '21 at 02:20

1 Answers1

1

As the comments have pointed out, instead of System.Threading.Thread.Sleep(5000), use await Task.Delay(TimeSpan.FromSeconds(5));. This would simulate doing five seconds of I/O (not five seconds of CPU computation) in each of the waiting tasks.

Mark Meuer
  • 7,200
  • 6
  • 43
  • 64