1

I know how to write a Parallel.For and a Parallel.ForEach loop. Here is the sample code for both of them:

Parallel.For(0,10, (int i) = > 
{
     Console.Writeline(i);
});  

Parallel.ForEach(fruits, fruit =>  
{  
     Console.WriteLine("Fruit Name: {0}, Thread Id= {1}", fruit, Thread.CurrentThread.ManagedThreadId);      
});

But the problem with both these code samples is the loops do not execute in sequence. How do I make them to execute in sequence? I have heard from people that you have to lock an object, then its possible. I have tried searching and tried lots of code samples but no use.

Furthermore, I would like to know whether the performance of parallel loops executed in sequence would be lesser or not? If no, why no? Because locking, would cause delay in my humble opinion.

As for my understanding of parallel programming, the scheduler makes the schedule at run-time. Can anyone tell what algorithm/strategy does .NET IDE use to schedule the code on several cores? Its goods to inside out of Parallel Programming.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Amir Diwan
  • 59
  • 7
  • They will execute in sequence, first **For** and then **ForEach**. But the result of them in their own scope is not guaranteed to be in sequence. – Shaharyar Dec 19 '15 at 11:32
  • If you want sequential execution, use `for` and `foreach`, any prerequisite for ordering of the collection will reduce it's performance when running in `Parallel` and may even be slower than a sequential loop – Yuval Itzchakov Dec 19 '15 at 12:10

1 Answers1

0

It doesn't really make sense for you to have threads run both in parallel and in sequence.

What happens if Thread 3 finishes before Thread 1? If you're going to block Thread 3 and make it wait until Thread 1 finishes, then what's the point in using threads, anyway?

If, however, you want batches to be done in sequence, it's possible but still not ideal.

By that, I mean, if you had a list [1,2,3,4,5,6,7,8,9,10] with 2 threads running, you could make sure that both 1 and 2 are processed before any other item, and so on. To do that, you could use something like this:

void Main()
{
    var items = Enumerable.Range(1, 100);
    const int numThreads = 4;

    foreach(var batch in items.Batch(numThreads))
    {
        var threads = batch.Select(item => {
            return new Thread(() => Console.WriteLine(item));
        }).ToList();

        threads.ForEach(t => t.Start());
        threads.ForEach(t => t.Join());
    }
}

public static class Ext
{
    public static IEnumerable<IEnumerable<TSource>> Batch<TSource>(
                    this IEnumerable<TSource> source, int size)
    {
        TSource[] bucket = null;
        var count = 0;

        foreach (var item in source)
        {
            if (bucket == null)
                bucket = new TSource[size];

            bucket[count++] = item;
            if (count != size)
                continue;

            yield return bucket;

            bucket = null;
            count = 0;
        }

        if (bucket != null && count > 0)
            yield return bucket.Take(count);
    }
}

Batch extension method taken from this answer

Community
  • 1
  • 1
Rob
  • 26,989
  • 16
  • 82
  • 98