I've been experimenting lately with async-await and I still cannot get some things to work.
Why does this code not always result with '100' being written to console?
Should not
await Task.WhenAll(tasks);
wait for all 100 tasks to complete?
static List<int> list = new List<int>();
static void Main(string[] args)
{
NewMethod();
Console.ReadLine();
}
private async static void NewMethod()
{
var tasks = new List<Task>();
for (int i = 0; i < 100; i++)
{
tasks.Add(Func(i));
}
Console.WriteLine("Lol");
await Task.WhenAll(tasks);
Console.WriteLine(list.Count());
}
static async Task Func(int i)
{
await Task.Delay(100);
list.Add(i);
}
Am I doing something wrong or is this some kind of async-await downside?
Same goes with
Task.WaitAll(tasks.ToArray());
which I wasn't sure at first if it's equal in this case.
There are a few similar questions but my example is really simple and I can't find explanation in the existing answers.
The reason you experience the inconsistency in the number of elements is because List<T>
isn't thread-safe .
After you await Task.Delay(100)
, the continuation, which adds elements to the list happens on an arbitrary thread pool, concurrently , because multiple tasks are executing. If you switch you implementation to use ConcurrentBag<int>
, this wont happen.
Try adding a lock(list) before adding the int to the list. You potentially adding from multiple threads to a non thread safe list.
The following code will work for your purposes:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApplication8
{
class Program
{
static readonly BlockingCollection<int> List = new BlockingCollection<int>();
static void Main(string[] args)
{
var application = NewMethod();
application.Wait();
Console.ReadLine();
}
private async static Task NewMethod()
{
var tasks = new List<Task>();
for (int i = 0; i < 100; i++)
{
tasks.Add(Func(i));
}
Console.WriteLine("Lol");
await Task.WhenAll(tasks);
Console.WriteLine(List.Sum());
}
static async Task Func(int i)
{
await Task.Delay(100);
List.Add(i);
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.