Home > OS >  C# Parallel.For() different iterations amount
C# Parallel.For() different iterations amount

Time:12-05

I'm trying to populate a list with a million independently generated items. But after the loop I'm getting less items: 999960, 998534 etc.

As a bypass I've wrapped this code in another that checks generated amount and generates missing items.

I've also tried to sleep after the loop, but it doesn't give a result closer to desired.

var someList = new List<ListItem>();
Parallel.For(0, 1000000, _ =>
{
    var item = new ListItem();

    //some logic here

    someList.Add(item);
});

System.Console.WriteLine(someList.Count()); // returns less than 1000000

What is the reason of such behaviour and what is the proper way to solve this task?

CodePudding user response:

If you know how many items you will generate, just use an array:

var someList = new ListItem[1000000];
Parallel.For(0, someList.Length, i =>
{
    var item = new ListItem();

    //some logic here

    someList[i] = item;
});

CodePudding user response:

The List<T> is not thread-safe. You can use a ConcurrentBag<T>, although that is an ICollection<T>, not an IList<T>. If you need the latter then you will have to synchronise the multiple threads, probably using a lock statement.

CodePudding user response:

When you want the results of a parallel operation, the PLINQ is more convenient than the Parallel class:

List<ListItem> results = Enumerable.Range(0, 1_000_000)
    .AsParallel()
    .Select(_ =>
    {
        ListItem item = new();

        // Some logic here

        return item;
    })
    .ToList();

A few differences that you should have in mind:

  1. The Parallel runs the code on the ThreadPool by default, but it's configurable. The PLINQ uses exclusively the ThreadPool.
  2. The Parallel by default has unlimited parallelism (it uses all the available threads of the ThreadPool). The PLINQ uses by default at most Environment.ProcessorCount threads.

The PLINQ by default doesn't preserve the order of the results. You can configure it with the AsOrdered if you want.

  • Related