我最近一直在尝试使用async-await,但仍然无法使用某些东西。
为什么这段代码并不总是因为'100'被写入控制台而导致?
不应该
await Task.WhenAll(tasks);
等待所有100个任务完成?
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);
}
我做错了什么或是某种异步 - 等待下行?
与
相同Task.WaitAll(tasks.ToArray());
在这种情况下,我一开始并不确定它是否相等。
有一些类似的问题,但我的例子非常简单,我在现有的答案中找不到解释。
答案 0 :(得分:11)
您遇到元素数量不一致的原因是List<T>
线程安全。
在await Task.Delay(100)
之后,向列表添加元素的continuation发生在任意线程池并发上,因为正在执行多个任务。如果您将实现切换为使用ConcurrentBag<int>
,则不会发生这种情况。
答案 1 :(得分:2)
在将int添加到列表之前尝试添加锁(列表)。您可能会从多个线程添加到非线程安全列表。
答案 2 :(得分:2)
以下代码适用于您的目的:
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);
}
}
}