Execute N threads and know when they all finished executing

3

I have the following problem, I need to run the same N method in a for and know when all the threads have already 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.
    
asked by anonymous 11.04.2015 / 01:06

2 answers

2

You can do this by using Parallels (i.e. PLINQ) or Tasks . I recommend that you use Tasks, because the PLINQ will probably become obsolete in the future.

Here's how:

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

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

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

    Since MetodoX would also 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 do not want to use any of these alternatives, do not want to use LINQ, PLINQ, or Tasks, and you want to manipulate Threads in hand, then you can do this:

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();
    
11.04.2015 / 01:34
2

You can use Tasks as recommended by Miguel Angelo and do it 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}");
    }
}

See working on dotNetFiddle .

In general it is not recommended to use raw Threads until there is a good reason to use it.

    
11.04.2015 / 14:57