Search code examples
c#multithreadingevent-wait-handle

How to run number of processes in bunches of thread without using threadPool & used EventWaitHandler for Handling


  class Process
{
    static void Main(string[] args)
    {
        int threads = 0;
        int processes = 0;
        Console.WriteLine("Total number of processes:");
        processes = Convert.ToInt32(Console.ReadLine());
        Console.WriteLine("Enter number of parallel threads:");
        threads = Convert.ToInt32(Console.ReadLine());

        ManualResetEvent[] events = new ManualResetEvent[threads];

        int k = 0, innercount = 0;           
        //----running in bunches
        do
        {
            for (int l = 0; l < threads; l++)
            {
                if (k < threads)
                {
                    events[l] = new ManualResetEvent(false);
                    Runner r = new Runner(events[l], innercount);
                    new Thread(new ThreadStart(r.Run)).Start();
                    Console.WriteLine("running start...{0}", innercount);
                    k++;
                    innercount++;
                }
            }
            WaitHandle.WaitAny(events);
            k--;
            Console.WriteLine("Decrement counter...{0}", k);
        }
        while (innercount < processes);

        WaitHandle.WaitAll(events);

        Console.WriteLine("All finished!");

        Console.ReadLine();

    }
}
 class Runner
{
    static readonly object rngLock = new object();
    static Random rng = new Random();

    ManualResetEvent ev;
    int id;

    internal Runner(ManualResetEvent ev, int id)
    {
        this.ev = ev;
        this.id = id;
    }

    internal void Run()
    {

            int sleepTime;
            lock (rngLock)
            {
                sleepTime = rng.Next(2000);
            }
            Thread.Sleep(sleepTime);
            Console.WriteLine("Thread Runner {0}",
                               id);
            if (ev.Set())
            {
                Console.WriteLine("release thread...{0}", id);
            }
    }
}

I have to run multiple threads.If one thread is finishes then start another thread.Problem is that its started all process at the same time.(Seems that this condition not working fine WaitHandle.WaitAny(events);)

1:If 20 threads are running then 21st will be started when One thread releases from 20s thread.

2: Without using threadpool can it be done using EventWaitHandler.


Solution

  • You could do something with PLinq and WithDegreeOfParallelism.

    WithDegreeOfParallelism will limit the number of threads that simultaneously run.

    The following example shows how to use Plinq to run a number of workers with limited parallelism passing a different object to each worker.

    It assumes that you start off with a sequence of objects, and you want to pass each of those objects to a worker method:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    
    namespace Demo
    {
        class DataForWorker
        {
            public int ID;
            public string Value;
        };
    
        class Program
        {
            Random rng = new Random();
            int numberOfThreadsRunning;
    
            void Run()
            {
                int maxThreads = 8;
    
                IEnumerable<DataForWorker> dataForWorkers = getDataForWorkers();
    
                dataForWorkers
                    .AsParallel()
                    .WithDegreeOfParallelism(maxThreads)
                    .ForAll(worker);
            }
    
            IEnumerable<DataForWorker> getDataForWorkers()
            {
                // Just return some dummy data.
    
                int numberOfDataItems = 30;
    
                return Enumerable.Range(1, numberOfDataItems).Select
                (
                    n => new DataForWorker
                    {
                        ID = n,
                        Value = n.ToString()
                    }
                );
            }
    
            void worker(DataForWorker data)
            {
                int n = Interlocked.Increment(ref numberOfThreadsRunning);
                Console.WriteLine("Thread " + data.ID + " is starting. #threads now = " + n);
                Thread.Sleep(rng.Next(1000, 2000));
                Console.WriteLine("Thread " + data.ID + " is stopping.");
                Interlocked.Decrement(ref numberOfThreadsRunning);
            }
    
            static void Main()
            {
                new Program().Run();
            }
        }
    }