Control of parallel foreach flow

511 Views Asked by At

I have to run two tasks using Parallel.ForEach but I want the first to finish and then start the second.

Parallel.Foreach(items, (item, state) =>
{
    Task1(item);
    Task2(item);
}
public void Task1(Item item)
{
    var records = GetRecordsToExport();
    UpdateFields1(records);
}
public void Task2(Item item)
{
    var content = File.Read(...);
    // read every line in content, and for every line update field DB
    foreach(var c in content)
    {
        UpdateFields2(c); // different methods
    }
}

This is the code, I can't post more as the code is pretty big

Task1 checks for some records into the DB that need updates and Task2 checks for the last updated records (those from Task1) and updates them again.

Initially I had the tasks the other way around and couldn't find out why program was crashing. This is because one task started before other one finished, and they operate on the same DB tables. How can I control the order of running?

2

There are 2 best solutions below

5
On BEST ANSWER

What you can do, is block the access to Task2, while there is any thread running in Task1. And the other way around, no thread is allowed to enter Task1, when any Task2 is still running.

I think you can try to use the ReaderWriterLockSlim:

var lock = new ReaderWriterLockSlim();


Parallel.Foreach(items, (item, state) =>
{
    lock.EnterReadLock();
    try {
        Task1(item);
    } finally {
        lock.ExitReadLock()
    }
    lock.EnterWriteLock();
    try {
        Task2(item);
    } finally {
        lock.ExitWriteLock()
    }
}

This code will also prevent any Task2 methods to be entered twice. If you need that, you can try to use Semaphore or Mutex. But this will make it more complicated.

0
On

It should not be possible for Task2 to operate on a an item that Task1 hasn't completed processing yet:

public class Test
{
    private static object syncObj = new object();

    public static void Main()
    {
        var items = Enumerable.Range(0, 100).ToArray();
        Parallel.ForEach(items, (item, state) =>
        {
            Task2(Task1(item));
        });
    }

    static int Task1(int item)
    {
        Console.WriteLine("Task 1 : {0}", item);
        Thread.Sleep(100);
        return item;
    }

    static int Task2(int item)
    {
        Console.WriteLine("Task 2 : {0}", item);
        return item;
    }
}