Create threads within a cycle

1

I have a problem I can not understand how to create threads within a cycle and that they all run simultaneously, and when all the threads are finished, send a message.

I have this code:

for (int i = 0; i <= x - 1; i++)
{
    if (File.Exists(fileList[i]))//valida que exista el archivo
    {
        FileInfo finfo = new FileInfo(fileList[i]);
        if (finfo.Extension == ".ctl") //valida que solo sean CTL
        {
            ExecuteBatFile(path, finfo.Name);//ejecuta proceso
        }
    }
}

and it is the procedure that executes the .batch file

// proceso para ejecutar un archivo .batch
 public  void ExecuteBatFile(string _path, string _archivoCTL)
        {

            CrearBatch(_path, _archivoCTL);
            Process proc = null;
            try
            {
                string targetDir = string.Format(_path);   //this is where mybatch.bat lies
                proc = new Process();
                proc.StartInfo.WorkingDirectory = targetDir;
                proc.StartInfo.FileName = _archivoCTL.Substring(0, _archivoCTL.Length - 4) + ".bat";
                proc.StartInfo.Arguments = string.Format("10");  //this is argument
                proc.StartInfo.CreateNoWindow = false;
                proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;  //this is for hiding the cmd window...so execution will happen in back ground.
                proc.Start();
                proc.WaitForExit();
            }
            catch (Exception ex)
            {
                MessageBox.Show("Exception Occurred :{0},{1}", ex.Message);
            }
        }

My question is where to create the threads so that they are executed simultaneously (so that the ExecuteBatFile is executed) and go checking if they are all finished.

Thank you very much for your advice. !!!

    
asked by elnapster 23.03.2018 в 19:08
source

3 answers

1

Creating a thread for each task that is usually done is a bad idea, if you create 50 threads it does not mean that all the threads run at the same time since the processors can only execute a limited number of tasks simultaneously, and if your goal is Run the tasks faster by creating many children you will get the opposite result. The most optimal is to create a thread for each core of the processor (assuming that there are no more applications running on the same PC) and create a queue where the tasks to be executed are placed where the threads are removing from the queue the tasks they execute. C # offers a class that optimizes the creation of threads. Example:

for (int i = 0; i <= x - 1; i++)
{
    if (File.Exists(fileList[i]))//valida que exista el archivo
    {
       FileInfo finfo = new FileInfo(fileList[i]);
       if (finfo.Extension == ".ctl") //valida que solo sean CTL
       {
        ThreadPool.QueueUserWorkItem( ExecuteBatFile());//colocar la tarea en la cola para ser ejecutada por alguno de los hilos del thread pool
       }
   }

}

    
answered by 23.03.2018 в 21:33
0

Thank you very much for the suggestion, based on your comment I have left it in the following way:

for (int i = 0; i <= x - 1; i++)
                    {
                        if (File.Exists(fileList[i]))//valida que exista el archivo
                        {
                            FileInfo finfo = new FileInfo(fileList[i]);
                              if (finfo.Extension == ".ctl") //valida que solo sean CTL
                                {
                               ThreadPool.QueueUserWorkItem(
                                    new WaitCallback(delegate (object state)
                                            { ExecuteBatFile(path, finfo.Name); }), null);
                                //clLog.Log("Ejecuta archivo batch " + finfo.Name);
                            }
                        }
                    }

Thanks !!!!

    
answered by 23.03.2018 в 22:19
0

If you use .net 4.5 (or higher) and Visual Studio 2012 at least, it is advisable to make the method asynchronous with the word async:

private async Task MetodoAsincrono(string path, string archivoCTL)
{
    await Task.Run(() => ExecuteBatFile(path, archivoCTL));
}

Then, to use it:

 private async Task EjecutaAsincrono()
 {
    var tasks = new List<Task>();

    for (int i = 0; i <= x - 1; i++)
    {
        if (File.Exists(fileList[i]))//valida que exista el archivo
        {
            FileInfo finfo = new FileInfo(fileList[i]);
            if (finfo.Extension == ".ctl") //valida que solo sean CTL
            {
                tasks.Add(MetodoAsincrono(path, finfo.Name)); // agregamos una a una cada tarea
            }
        }
   }

  await Task.WhenAll(tasks.ToArray()); // ejecutamos todas las tareas programadas y espera a que terminen
  // aquí envías el mensaje
}

Currently, it is advisable to use async / await for asynchronous tasks. I do not see logic in using ThreadPool.QueueUserWorkItem when there is async / await, ThreadPool.QueueUserWorkItem is an outdated super api (.net 1.1), it is no longer recommended, unless you are anchored in old versions of the framwork.

    
answered by 25.03.2018 в 03:14