Spawn Multiple Threads for work then wait until all finished

后端 未结 12 1509
遇见更好的自我
遇见更好的自我 2020-11-28 01:46

just want some advice on \"best practice\" regarding multi-threading tasks.

as an example, we have a C# application that upon startup reads data from various \"type

相关标签:
12条回答
  • 2020-11-28 02:14

    If you are using .NET 3.5 or below, you can use an array of AsyncResult or BackgroundWorker and count how many threads have returned (just don't forget to decrease counter with interlocked operations) (see http://www.albahari.com/threading/ as a reference).

    If you are using .NET 4.0 a parallel for is the simplest approach.

    0 讨论(0)
  • 2020-11-28 02:18

    Posting to maybe help some others, spent quite a bit of time looking for a solution like what I came up with. So I took a little different approach. I was spinning off numerous threads and incremented a counter and decremented a counter as a thread started and stopped. Then in the main method I was wanting to pause and wait for threads to complete I did.

    while (threadCounter > 0)
    {
        Thread.Sleep(500); //Make it pause for half second so that we don’t spin the cpu out of control.
    }
    

    Documented on my blog. http://www.adamthings.com/post/2012/07/11/ensure-threads-have-finished-before-method-continues-in-c/

    0 讨论(0)
  • 2020-11-28 02:19

    Assuming the database reader threads return as soon as they're done, you can simply call Thread.Join on all ten threads in turn from the initiating thread.

    0 讨论(0)
  • 2020-11-28 02:20

    If you're feeling adventurous you can use C# 4.0 and the Task Parallel Library:

    Parallel.ForEach(jobList, curJob => {
      curJob.Process()
    });
    
    0 讨论(0)
  • 2020-11-28 02:20

    Just for fun, what @Reed has done, with Monitor. :P

    class Program
    {
        static void Main(string[] args)
        {
            int numThreads = 10;
            int toProcess = numThreads;
            object syncRoot = new object();
    
            // Start workers.
            for (int i = 0; i < numThreads; i++)
            {
                new Thread(delegate()
                {
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                    // If we're the last thread, signal
                    if (Interlocked.Decrement(ref toProcess) == 0)
                    {
                        lock (syncRoot)
                        {
                            Monitor.Pulse(syncRoot);
                        }
                    }
                }).Start();
            }
    
            // Wait for workers.
            lock (syncRoot)
            {
                if (toProcess > 0)
                {
                    Monitor.Wait(syncRoot);
                }
            }
    
            Console.WriteLine("Finished.");
        }
    }
    
    0 讨论(0)
  • 2020-11-28 02:22

    My preference for this is to handle this via a single WaitHandle, and use Interlocked to avoid locking on a counter:

    class Program
    {
        static void Main(string[] args)
        {
            int numThreads = 10;
            ManualResetEvent resetEvent = new ManualResetEvent(false);
            int toProcess = numThreads;
    
            // Start workers.
            for (int i = 0; i < numThreads; i++)
            {
                new Thread(delegate()
                {
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                    // If we're the last thread, signal
                    if (Interlocked.Decrement(ref toProcess) == 0)
                        resetEvent.Set();
                }).Start();
            }
    
            // Wait for workers.
            resetEvent.WaitOne();
            Console.WriteLine("Finished.");
        }
    }
    

    This works well, and scales to any number of threads processing, without introducing locking.

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