-2

我正在尝试将所有任务并行添加到列表中,然后等待它们。代码:

List<Task<bool>> tasks = new List<Task<bool>>();                

Parallel.For(0, 500, file =>
{
  tasks.Add(SomeTask());
});

Console.WriteLine("Total tasks = " + tasks.Count);

当我执行以下代码时,有时我会得到任务列表(tasks.Count)的大小为 493 或 500 或 498。但这不是确定性的。我应该怎么办?

4

2 回答 2

1

你有所谓的竞争条件。您在没有同步的情况下从多个线程访问列表,这导致它处于奇怪的状态。

您可以改用 ConcurrentStack 之类的线程安全对象(或 ConcurrentBag 或 ConcurrentQueue,具体取决于您对集合执行的操作):

ConcurrentStack<Task<bool>> tasks = new ConcurrentStack<Task<bool>>();                

Parallel.For(0, 500, file =>
{
  tasks.Push(SomeTask());
});

Console.WriteLine("Total tasks = " + tasks.Count);
于 2019-02-28T13:57:28.420 回答
1

任务返回方法(例如SomeTask)通常返回非常快,并且并行化它们的调用通常会导致执行速度变慢

使用(非并行)LINQ 构建任务集合更为正常:

var tasks = Enumerable.Range(0, 500).Select(file => SomeTask()).ToList();
Console.WriteLine("Total tasks = " + tasks.Count);

如果您的任务返回方法有一些受 CPU 限制的代码,并且您确实需要SomeTask在线程池线程上运行,那么您可以使用并行性。一种简单的方法是将调用包装在Task.Run

var tasks = Enumerable.Range(0, 500).Select(file => Task.Run(() => SomeTask())).ToList();
Console.WriteLine("Total tasks = " + tasks.Count);
于 2019-02-28T15:16:40.377 回答