简体   繁体   中英

how to make Wait until all threads finished it's work from threadpool in c#

for (int task = 0; task < 20; task++)
{

    ThreadPool.QueueUserWorkItem(new WaitCallback(TaskCallBack), new object[] { filepath1, filepath2, 
                  filepath3 });

}

public static void TaskCallBack(object state)
{
            object[] array = state as object[];
            string filea = Convert.ToString(array[0]);
            string fileb = Convert.ToString(array[1]);
            string filec = Convert.ToString(array[2]);
            //something below         

}

I want main thread to be waited until all threads finishes its work. Please help

The best way to handle this would be to use Task.Run() and Task.WhenAll() , or to use Parallel.Invoke() .

However, if you need to use ThreadPool.QueueUserWorkItem you can solve this issue as follows:

  1. For ease of use, encapsulate all the data that you want to pass to the thread in a class. This data should include an instance of CountdownEvent initialised with a count equal to the number of threads you want to wait for. (In the sample code below, this class is called ThreadData .)
  2. Inside your TaskCallBack() methods, call CountdownEvent.Signal() when the method has completed.
  3. Inside the main thread, start all the threadpool threads and then call CountdownEvent.Wait() to wait for all the threads to complete.

Putting this all together in a compilable console app:

using System;
using System.Threading;

namespace CoreConsole
{
    public sealed class ThreadData
    {
        public ThreadData(CountdownEvent countdown, int index)
        {
            Countdown = countdown;
            Index     = index;
        }

        public CountdownEvent Countdown { get; }
        public int Index { get; }
    }

    public static class Program
    {
        static void Main()
        {
            int n = 20;
            var countdown  = new CountdownEvent(n);

            for (int task = 0; task < n; task++)
            {
                ThreadPool.QueueUserWorkItem(TaskCallBack, new ThreadData(countdown, task));
            }

            Console.WriteLine("Waiting for all threads to exit");

            countdown.Wait();

            Console.WriteLine("Waited for all threads to exit");
        }

        public static void TaskCallBack(object state)
        {
            var data = (ThreadData) state;

            Console.WriteLine($"Thread {data.Index} is starting.");

            Thread.Sleep(_rng.Next(2000, 10000));
            data.Countdown.Signal();

            Console.WriteLine($"Thread {data.Index} has finished.");
        }

        static readonly Random _rng = new Random(45698);
    }
}

The ThreadData.Index property is just used to identify each thread in the Console.WriteLine() calls.

Note: In real code, it is important to always signal the Countdown event, even if the thread throws an exception - so you should wrap the code in a try/finally like so:

public static void TaskCallBack(object state)
{
    var data = (ThreadData)state;

    try
    {
        // Do work here.
        Console.WriteLine($"Thread {data.Index} is starting.");
        Thread.Sleep(_rng.Next(2000, 10000));
        Console.WriteLine($"Thread {data.Index} has finished.");
    }

    finally
    {
        data.Countdown.Signal();
    }
}

Like @Ackdari mentioned in his comment, you could use Task.Run . But you don't need the await keyword. Just create a collection with the tasks and wait for it.

Example:

// Create a list that will hold the tasks
List<Task> tasks = new List<Task>;

// Create the tasks
for (int taskId = 0; taskId < 20; task++)
{
  tasks.Add(Task.Run(() => { TaskCallBack(new object[] { filepath1, filepath2, filepath3 }); }));
}

// Wait for ALL tasks to complete
Task.WaitAll(tasks.ToArray());

That way you could also use your own method that will be run by the task. Example:

public static void ReplaceWithABetterName(string[] filePaths)
{
   string filea = filePaths[0);
   string fileb = filePaths[1];
   string filec = filePaths[2];
   //do stuff       
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM