C# Waiting for multiple threads to finish

后端 未结 5 1669
滥情空心
滥情空心 2020-11-28 12:30

I have a windows forms app that I am checking all the serial ports to see if a particular device is connected.

This is how I spin off each thread. The below code is

相关标签:
5条回答
  • 2020-11-28 12:53

    You can use a CountDownLatch:

    public class CountDownLatch
    {
        private int m_remain;
        private EventWaitHandle m_event;
    
        public CountDownLatch(int count)
        {
            Reset(count);
        }
    
        public void Reset(int count)
        {
            if (count < 0)
                throw new ArgumentOutOfRangeException();
            m_remain = count;
            m_event = new ManualResetEvent(false);
            if (m_remain == 0)
            {
                m_event.Set();
            }
        }
    
        public void Signal()
        {
            // The last thread to signal also sets the event.
            if (Interlocked.Decrement(ref m_remain) == 0)
                m_event.Set();
        }
    
        public void Wait()
        {
            m_event.WaitOne();
        }
    }
    

    Example how to use it:

    void StartThreads
    {
        CountDownLatch latch = new CountDownLatch(availPorts.Count);
    
        foreach (cpsComms.cpsSerial ser in availPorts)
        {
            Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));
    
            //start thread and pass it the port and the latch
            t.Start((object)new Pair(ser, latch));
    
        }
    
        DoSomeWork();
    
        // wait for all the threads to signal
        latch.Wait();
    
        DoSomeMoreWork();
    }
    
    // In each thread
    void NameOfRunMethod
    {
        while(running)
        {
            // do work
        }
    
        // Signal that the thread is done running
        latch.Signal();
    }
    
    0 讨论(0)
  • 2020-11-28 13:06
    List<Thread> threads = new List<Thread>();
    foreach (cpsComms.cpsSerial ser in availPorts)
    {
        Thread t = new Thread(new ParameterizedThreadStart(lookForValidDev));
        t.Start((object)ser);//start thread and pass it the port
        threads.Add(t);
    }
    foreach(var thread in threads)
    {
        thread.Join();
    }
    

    Edit

    I was looking back at this, and I like the following better

    availPorts.Select(ser =>
          {
              Thread thread = new Thread(lookForValidDev);
              thread.Start(ser);
              return thread;
          }).ToList().ForEach(t => t.Join());
    
    0 讨论(0)
  • 2020-11-28 13:11

    The simplest and safest way to do this is to use a CountdownEvent. See Albahari.

    0 讨论(0)
  • 2020-11-28 13:14

    Use the AutoResetEvent and ManualResetEvent Classes:

    private ManualResetEvent manual = new ManualResetEvent(false);
    void Main(string[] args)
    {
        AutoResetEvent[] autos = new AutoResetEvent[availPorts.Count];
    
        manual.Set();
    
        for (int i = 0; i < availPorts.Count - 1; i++)
            {
    
            AutoResetEvent Auto = new AutoResetEvent(false);
            autos[i] = Auto;
    
            Thread t = new Thread(() => lookForValidDev(Auto, (object)availPorts[i]));
            t.Start();//start thread and pass it the port  
    
        }
        WaitHandle.WaitAll(autos);
        manual.Reset();
    
    }
    
    
    void lookForValidDev(AutoResetEvent auto, object obj)
    {
        try
        {
             manual.WaitOne();
             // do something with obj 
        }
        catch (Exception)
        {
    
        }
        finally
        {
            auto.Set();
        }
    
    
    } 
    
    0 讨论(0)
  • 2020-11-28 13:15

    Store the Thread results in a list after they were spawned and iterate the list - during iteration call join then. You still join linearly, but it should do what you want.

    0 讨论(0)
提交回复
热议问题