Wait until all threads finished their work in ThreadPool

后端 未结 5 448
不知归路
不知归路 2020-12-09 10:28

i have this code:

var list = new List();
for(int i=0;i<10;i++) list.Add(i); 
for(int i=0;i<10;i++)
{
     ThreadPool.QueueUserWorkItem(
             


        
相关标签:
5条回答
  • 2020-12-09 10:35

    This is how I would do it.

    class Program
    {
        static void Main(string[] args)
        {
            var items = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
            using (var countdown = new Countdown(items.Length))
            {
                foreach (var item in items)
                {
                    ThreadPool.QueueUserWorkItem(o =>
                    {
                        Thread.SpinWait(100000000);
                        Console.WriteLine("Thread Done!");
                        countdown.Signal();
                    });
                }
                countdown.Wait();
            }
            Console.WriteLine("Job Done!");
            Console.ReadKey();
        }
    
        public class Countdown : IDisposable
        {
            private readonly ManualResetEvent done;
            private readonly int total;
            private volatile int current;
    
            public Countdown(int total)
            {
                this.total = total;
                current = total;
                done = new ManualResetEvent(false);
            }
    
            public void Signal()
            {
                lock (done)
                {
                    if (current > 0 && --current == 0)
                        done.Set();
                }
            }
    
            public void Wait()
            {
                done.WaitOne();
            }
    
            public void Dispose()
            {
                done.Dispose();
            }
        }
    } 
    
    0 讨论(0)
  • 2020-12-09 10:36

    In .NET Framework 4+ use the handy System.Threading.CountdownEvent class:

    const int threadCount = 10;
    var list = new List<int>(threadCount);
    for (var i = 0; i < threadCount; i++) list.Add(i);
    
    using (var countdownEvent = new CountdownEvent(threadCount))
    {
        for (var i = 0; i < threadCount; i++)
            ThreadPool.QueueUserWorkItem(
                x =>
                {
                    Console.WriteLine(x);
                    countdownEvent.Signal();
                }, list[i]);
    
        countdownEvent.Wait();
    }
    Console.WriteLine("done");
    
    0 讨论(0)
  • 2020-12-09 10:37

    The thread pool does not tell you when the thread has finished executing, so the work item must do it itself. I changed the code like this:

        var list = new List<int>();
        ManualResetEvent[] handles = new ManualResetEvent[10];
        for (int i = 0; i < 10; i++) {
            list.Add(i);
            handles[i] = new ManualResetEvent(false);
        }
        for (int i = 0; i < 10; i++) {
            ThreadPool.QueueUserWorkItem(
             new WaitCallback(x =>
             {
                 Console.WriteLine(x);
                 handles[(int) x].Set();
             }), list[i]);
        }
    
        WaitHandle.WaitAll(handles);
    
    0 讨论(0)
  • 2020-12-09 10:39

    You'll need to track this yourself.

    One option for this is to use a counter and a reset event:

    int toProcess = 10;
    using(ManualResetEvent resetEvent = new ManualResetEvent(false))
    {
        var list = new List<int>();
        for(int i=0;i<10;i++) list.Add(i); 
        for(int i=0;i<10;i++)
        {
            ThreadPool.QueueUserWorkItem(
               new WaitCallback(x => {
                  Console.WriteLine(x);  
                  // Safely decrement the counter
                  if (Interlocked.Decrement(ref toProcess)==0)
                     resetEvent.Set();
    
               }),list[i]);
        } 
    
        resetEvent.WaitOne();
    }
    // When the code reaches here, the 10 threads will be done
    Console.WriteLine("Done");
    
    0 讨论(0)
  • 2020-12-09 10:52

    I am not sure if ThreadPool exposes such functionality but you can use wait handles and by the way iterating twice seems unnecessary:

    var events = new ManualResetEvent[10];
    var list = new List<int>();
    for (int i = 0; i < 10; i++)
    {
        list.Add(i);
        events[i] = new ManualResetEvent(false);
        int j = i;
        ThreadPool.QueueUserWorkItem(x => {
            Console.WriteLine(x);
            events[j].Set();
        }, list[i]);
    }
    WaitHandle.WaitAll(events);
    
    0 讨论(0)
提交回复
热议问题