Click here to Skip to main content
15,884,962 members
Please Sign up or sign in to vote.
3.00/5 (1 vote)
See more:
I am facing a problem in threading while i have to run 10 threads at a time
each thread calls same function and as any of the thread gets its job done how would i run the next thread again
as thread count become 9 or less

Note: there is a condition that 10 threads will be running all the time.
Posted

Have you given a thought to use thread pool instead of creating and using 10 different threads. For me it look like perfect place to use thread pool where you can set the min number thread to 10 so there will be always 10 thread running till there is work to process.

See the link below to know more about Thread Pool

http://msdn.microsoft.com/en-us/library/system.threading.threadpool.aspx[^]
 
Share this answer
 
Comments
NavneetArora 20-May-11 6:08am    
but is that possible for running 10 thread of n threads
CS2011 20-May-11 6:57am    
Did you understand how the Threadpool works.Please use google to get an idea how this thing works.
NavneetArora 20-May-11 6:11am    
if yess plz provide a code
CS2011 20-May-11 6:58am    
will try for this when i get time...may be in a day or 2
Depends on how you are generating your threads.
If you are using a BackgroundWorker thread, then handle the BackgroundWorker.RunWorkerCompleted Event[^] and start a new one if the old one hasn't failed for some reason.

There is a similar mechanism in the other threading systems.
 
Share this answer
 
Comments
NavneetArora 20-May-11 5:35am    
sorry i am not using bckgrnd worker am using simple multi threading mechanism
OriginalGriff 20-May-11 6:04am    
Then that will have a similar mechanism.
Hi,

What is the nature of the work being done? you say each thread is calling the same method, but is it calling the same method with different parameters?

I ask this because I have implemented somewhat similar solutions in the past, where an array of threads consumes work from a queue.

The basic structure is that you build an array of (say 10) threads, and initialize each of these to the same method. The common method gets the parameters for it's work off a FIFO queue, does the work, then loops round to consume the next task. When all ten threads are initiated to the same queue, the work will be done simultaneously as long as there is a job for each thread.

You need to implement some locking to ensure that two threads cannot consume the same task. Also, to stop the threads thrashing away without any work to be done, you need to have them wait on an event before checking the queue for work.

You can design in events to be raised when a thread completes a task, and/or when the queue becomes empty.

This is basically the .NET thread-pool, but sometimes if you are doing some very specific work it can pay to develop your own version, where you have complete control and you are not passing delegates for each task(which takes additional overhead, and can cost some additional CPU cycles)

Here is a quick and dirty example of what I am talking about: (please note I haven't actually compiled this code it might not be 100%, but I have used this sort of pattern numerous times in the past, the concept definitely works)

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;

/// <summary>
/// example utilizing an array of threads to consume tasks from a queue
/// </summary>
public class WorkerPoolExample
{
    /// <summary>
    /// arguments for the task
    /// </summary>
    private class TaskArguments
    {
        public int A { get; set; }
        public int B { get; set; }
    }

    /// <summary>
    /// pool of threads.
    /// </summary>
    private Thread[] _pool;

    /// <summary>
    /// sync object for the work queue.
    /// </summary>
    private object _queueLocker = new object();

    /// <summary>
    /// event to signal new work on the queue.
    /// </summary>
    private AutoResetEvent _newWorkEvent = new AutoResetEvent(false);

    /// <summary>
    /// queue of tasks.
    /// </summary>
    private Queue<TaskArguments> _workQueue = new Queue<TaskArguments>();

    /// <summary>
    /// run flag
    /// </summary>
    private bool _runFlag = true;

    /// <summary>
    /// event raised on completion of each task.
    /// </summary>
    public event EventHandler TaskComplete;

    /// <summary>
    /// construct the class and start the thread-pool.
    /// </summary>
    /// <param name="threadCount"></param>
    public WorkerPoolExample(int threadCount)
    {
        // construct the pool
        _pool = new Thread[threadCount];

        // create and start each thread.
        for (int i = 0; i < _pool.Length; i++)
        {
            _pool[i] = new Thread((ThreadStart)ConsumerTask);
            _pool[i].Start();
        }

        // handle the application-exit event to terminate the thread-pool.
        Application.ApplicationExit += delegate
        {
            _runFlag = false;
            _newWorkEvent.Set();
        };
    }

    /// <summary>
    /// add a new task to the queue.
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    public void AddTask(int a, int b)
    {
        AddTask(new TaskArguments() { A = a, B = b });
    }

    /// <summary>
    /// add a new task to the queue.
    /// </summary>
    /// <param name="args"></param>
    public void AddTask(TaskArguments args)
    {
        // synchronize access to the queue
        lock (_queueLocker)
        {
            // add the task.
            _workQueue.Enqueue(args);
        }

        // signal the threads a new item is on the queue.
        _newWorkEvent.Set();
    }

    /// <summary>
    /// add a block of tasks.
    /// </summary>
    /// <param name="args"></param>
    public void AddTaskRange(TaskArguments[] args)
    {
        lock (_queueLocker)
        {
            foreach (var task in args)
                _workQueue.Enqueue(task);
        }
        _newWorkEvent.Set();
    }

    /// <summary>
    /// consumes tasks from the queue.
    /// </summary>
    private void ConsumerTask()
    {
        // loop while the flag is true.
        while (_runFlag)
        {
            // wait on the auto-reset event:
            _newWorkEvent.WaitOne();

            // check work is on the queue:
            if (_workQueue.Count > 0)
            {
                // dequeue a single task:
                TaskArguments args = null;
                lock (_queueLocker)
                {
                    args = _workQueue.Dequeue();
                }

                // process the task:
                if (args != null)
                {
                    DoWorkMethod(args);
                    if (TaskComplete != null)
                        TaskComplete(args, new EventArgs());
                }
            }

        }
    }

    /// <summary>
    /// the work being done.
    /// </summary>
    private void DoWorkMethod(TaskArguments args)
    {
        Console.WriteLine(args.A + args.B);
        Thread.Sleep(100);
    }

}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900