Lock code by string name with parallelism in C#

89 Views Asked by At

I have the following code:

string[] arr = ["A", "B", "B", "B", "B", "B", "C"];

var options = new ParallelOptions() { 
    MaxDegreeOfParallelism = 3 
};

Parallel.ForEach(arr, options , res =>
{
    // No double res with the same name is allowed
    // Code with res
});

I want the code in the parallel loop to be able to execute A and B at the same time and wait for the first B to finish in order to move to the next B.

In other word, it is not allowed to run the code on the same res at the same time.

With named semaphore, if I want to create a semaphore at runtime, it can't be static.

How can I resolve this issue?

Thanks

1

There are 1 best solutions below

4
Peter B On

You can do this by grouping the items, and then run the Parallel.ForEach() on the groups.

Code (in which I added suffixes to the Bs so we can distinguish them):

string[] arr = ["A", "B1", "B2", "B3", "B4", "B5", "C"];
var groups = arr.GroupBy(x => x[0]).ToArray();

var options = new ParallelOptions() { MaxDegreeOfParallelism = 3 };

Parallel.ForEach(groups, options, group =>
{
    foreach (var res in group)
    {
        Console.WriteLine("Start " + res);
        Thread.Sleep(50 + rnd.Next(1000));
        Console.WriteLine("End   " + res);
    }
});
Thread.Sleep(4500);
Console.WriteLine("Done");

Working Fiddle: https://dotnetfiddle.net/t5wm1a

Output run 1:

Start A
Start B1
Start C
End   B1
Start B2
End   C
End   A
End   B2
Start B3
End   B3
Start B4
End   B4
Start B5
End   B5
Done

Output run 2:

Start C
Start B1
Start A
End   A
End   B1
Start B2
End   C
End   B2
Start B3
End   B3
Start B4
End   B4
Start B5
End   B5
Done

The output shows:

  • No B starts until the previous B has ended.
  • A and C run in parallel with all of the Bs.

Update: initially I used Task.Delay but Thread.Sleep is better in this scenario (see comments below).