0

I have a function that has two parts. need all the success of the first part before execute the second part.

Such as:

ConcurrentDictionary<string, string> _dic = new ConcurrentDictionary<string, string>();
var _taskList = new List<Task>();
foreach (var item in someDataList)
{ 
    _taskList.Add(new Task(async () =>
    { 
        var result = await _req.ExecuteAsync(someParams).ConfigureAwait(false);
         _dic.TryAdd(result.data, result.data);
    }
}
_taskList.ForEach(t => t.Start());
await Task.WhenAll(_taskList.ToArray()).ConfigureAwait(false);

if (_dic.Count == List.count()
{
    //execute part 2.
}

not waiting for all tasks to be completed, there is no data in the dictionary at any time. and i try:

 while (true)
{
    foreach (var item in _taskList)
    {
       if (item.Status == TaskStatus.Running)
          goto continueWait;
    }
}


but it didn't work either.

Why is that? What should I do?

2 Answers2

4

There won't be any data in your dict because passing in an async lambda is not going to make any difference in Task's ctor.

You will need to restructure your code quite a bit. You want to call your async method, put the Task in your list and then await till of them complete. Once they're completed, then can you iterate over all your results in your task list and pull out the .Result from it.

var tasks = someDataList.Select(i => _req.ExecuteAsync(i) );
await Task.WhenAll(tasks);
var dict = tasks.ToDictionary(t=> t.Result);
if (dict.Count == List.count()
{
    //execute part 2.
}

Note that if _dict is a global variable and you need locking, then you should just replace ToDictionary with your ConcurrentDictionary code above as this is example code.

JohanP
  • 5,252
  • 2
  • 24
  • 34
  • 2
    Just to expand on "an `async` lambda is not going to make any difference in `Task`'s ctor" - All the [constructors of `Task`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task) take an [`Action`](https://learn.microsoft.com/en-us/dotnet/api/system.action), which is basically a `void` method. That means your anonymous function that you're giving it is interpreted as `async void`, which means that it cannot be awaited. – Gabriel Luci Dec 09 '19 at 02:19
  • I would highly recommend against using `.Result` even here. You can simply await the same task and get the result. [Await on a completed task same as task.Result?](https://stackoverflow.com/questions/24623120/await-on-a-completed-task-same-as-task-result) – Erik Philips Dec 09 '19 at 02:58
0

The code below example of async loop

var series = Enumerable.Range(1, 5).ToList();
    var tasks = new List<Task<Tuple<int, bool>>>();
    foreach (var i in series)
    {
        Console.WriteLine("Starting Process {0}", i);
        tasks.Add(DoWorkAsync(i));
    }
    foreach (var task in await Task.WhenAll(tasks))
    {
        if (task.Item2)
        {
            Console.WriteLine("Ending Process {0}", task.Item1);
        }
    }
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
Jaha
  • 159
  • 5
  • 18