Parallel.For循环退出太早

时间:2019-02-28 13:44:05

标签: c# multithreading task parallel.for

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

DataTable dt_LearnDelivery = new DataTable();

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

2 个答案:

答案 0 :(得分:1)

您拥有所谓的race condition。您正在从多个线程访问列表而不进行同步,这会使列表处于怪异状态。

您可以改用像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);

答案 1 :(得分: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);