Home > Enterprise >  Is there a way to run 2 for loops at the same time but one is dependent on the other?
Is there a way to run 2 for loops at the same time but one is dependent on the other?

Time:09-09

Suppose I have these 2 for loops:

Loop a:

for (int i = 0; i < 10; i  )
{
    Task.Delay(1000)
}

Loop B:

for (int i = 0; i < 10; i  )
{
    Task.Delay(200)
}

I want to run the loops and loop B should only run after each index of A is complete (The index of B should always be lower than A). When loop B runs, I don't want loop A to pause until loop B is complete. Is there a way to do this?

Note: The Task.Delay is just a placeholder

CodePudding user response:

You can use this quick and dirty SemaphoreSlim (though not a very correct one) approach (also needs some exception handling and cancelation support):

var sw = Stopwatch.StartNew();
int capacity = 10;
var semaphoreSlim = new SemaphoreSlim(0, capacity);
var t1 = Task.Run(async () =>
{
    for (int i = 0; i < capacity; i  )
    {
        await Task.Delay(500);
        semaphoreSlim.Release();
    }
});

var t2 = Task.Run(async () =>
{
    for (int i = 0; i < capacity; i  )
    {
        await semaphoreSlim.WaitAsync();
        await Task.Delay(200);
    }
});

await Task.WhenAll(t1, t2);
Console.WriteLine(sw.ElapsedMilliseconds);

Or look into some producer-consumer approach like here or using System.Threading.Channels (again simplified example which lacks error handling and cancelation support):

var sw = Stopwatch.StartNew();
int capacity = 10;
var bounded = Channel.CreateBounded<int>(capacity);

var t1 = Task.Run(async () =>
{
    for (int i = 0; i < capacity; i  )
    {
        await Task.Delay(500);
        await bounded.Writer.WriteAsync(i);
    }
    bounded.Writer.Complete();
});

var t2 = Task.Run(async () =>
{
    while (await bounded.Reader.WaitToReadAsync())
    {
        var readAsync = await bounded.Reader.ReadAsync();
        await Task.Delay(200);
    }
});

await Task.WhenAll(t1, t2);
Console.WriteLine(sw.ElapsedMilliseconds);

CodePudding user response:

An array of Booleans can be used to achieve what you want.

The following would prevent iterations in B from continuing without the iteration for the same indexing in A having been completed.

private const int NoOfIndexes = 100;
private static bool[] IndexesComplete = new bool[NoOfIndexes];
public static void Main()
{
    Task.WaitAll(RunLoopA(), RunLoopB());
}

public static async Task RunLoopA() 
{
    for (int i = 0; i < NoOfIndexes; i  )
    {
        //Main loop work
        Console.WriteLine($"A {i}");
        //End of main loop work
       
        IndexesComplete[i] = true;
        await Task.Delay(50);
    }
}

public static async Task RunLoopB()
{
    for (int i = 0; i < NoOfIndexes; i  )
    {
        while (!IndexesComplete[i])
        {
            await Task.Delay(50);
        }

        //Main loop work
        Console.WriteLine($"B {i}");
        //End of main loop work
    }
}
  •  Tags:  
  • c#
  • Related