Run N threads and know when all finished running

Asked

Viewed 429 times

3

I have the following problem, I need to run the same method N times in a for and know when all the threads they’ve finished running it.

I needed something like this:

foreach (MeuObjeto obj in lstObj)
{
    new Thread(delegate() { MetodoX(obj ); }).Start();             
}  
metodoY(); // só rodar depois que todas as thread  acima já tiverem terminado.

2 answers

2


It is possible to do this using Parallels (i.e. PLINQ) or Tasks. I recommend using Tasks, as PLINQ will probably eventually become obsolete in favor of the previous.

See how to do:

  • using the method ForAll of the PLINQ... is the simplest of all:

    lstObj.AsParallel().ForAll(MetodoX);
    metodoY();
    
  • using Task.WhenAll: simple call, modified method

    var manyTasks = lstObj.Select(MetodoX); // a chamada fica símples
    Task.WhenAll(manyTasks).Wait();
    metodoY();
    

    Whereas the MetodoX would have to be changed to use async and await:

    private async Task MetodoX(MeuObjeto obj)
    {
        await Task.Yield(); // primeira linha do método deve ser um Yield
    
  • using Task.WhenAll and Task.Run: less simple call, original method

    var manyTasks = lstObj.Select(x => Task.Run(() => MetodoX(x)));
    Task.WhenAll(manyTasks).Wait();
    metodoY();
    

If you still don’t want to use any of these alternatives, don’t want to use LINQ, PLINQ, or Tasks, and want to handle Threads by hand, then you can do so:

var threads = new List<Thread>();
foreach (string obj in lstObj)
    threads.Add(new Thread(delegate() { MetodoX(obj); }));

foreach (var thread in threads)
    thread.Start();

foreach (var thread in threads)
    thread.Join();

2

It is possible to use Tasks as recommended by Miguel Anelo and do in a simplified way without worrying about the mechanism:

using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
                    
public class Program {
    public static void Main() {
        var lstObj = new List<int> { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 };
        Parallel.ForEach(lstObj, obj => MetodoX(obj));
        Console.WriteLine("Fim"); //aqui poderia ser o MetodoY()
    }
    public static void MetodoX(int obj) {
        Console.WriteLine($"ThreadID: {Thread.CurrentThread.ManagedThreadId, 3}, Valor: {obj}");
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

In general it is not recommended to use Threads rough until there’s a good reason to use.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.