huda
huda

Reputation: 4297

How to use ThreadPool class

namespace ThPool
{
    class Program
    {
        private static long val = 0;
        private static string obj = string.Empty;

        static void Main(string[] args)
        {
            Thread objThread1 = new Thread(new ThreadStart(IncrementValue));
            objThread1.Start();
            Thread objThread2 = new Thread(new ThreadStart(IncrementValue));
            objThread2.Start();
            objThread1.Join();
            objThread2.Join();

            Console.WriteLine("val=" + val + " however it should be " + (10000000 + 10000000));

            Console.ReadLine();
        }

        private static void IncrementValue()
        {
            for (int i = 0; i < 10000000; i++)
            {
                Monitor.Enter(obj);
                val++;
                Monitor.Exit(obj);
            }
        }
    }
}

How do I use ThreadPool class in replacement of thread & monitor?

Upvotes: 5

Views: 2836

Answers (5)

tuinstoel
tuinstoel

Reputation: 7316

You can use BeginInvoke, EndInvoke. It uses the threadpool behind the scenes but it is easier to program. See here:

http://msdn.microsoft.com/en-us/library/2e08f6yc.aspx

Upvotes: 0

Matt Davison
Matt Davison

Reputation: 1552

Do not use the thread pool for anything but the most simple things. In fact it is extremely dangerous to aquire a lock on a thread pool thread. However you can safely use the Interlocked API's.

Upvotes: 0

Pablo Retyk
Pablo Retyk

Reputation: 5758

EventWaitHandle[] waitHandles = new EventWaitHandle[2];


for(int i = 0; i < 2; i++)
{
    waitHandles[i] = new AutoResetEvent(false);
    ThreadPool.QueueUserWorkItem(state =>
    {
        EventWaitHandle handle = state as EventWaitHandle;
        for(int j = 0; j < 10000000; j++)
        {
            Interlocked.Increment(ref val); //instead of Monitor
        }
        handle.Set();
    }, waitHandles[i]);
}

WaitHandle.WaitAll(waitHandles);
Console.WriteLine("val=" + val + " however it should be " + (10000000 + 10000000));

Upvotes: 2

Brian Rasmussen
Brian Rasmussen

Reputation: 116481

There are a couple of ways to use the thread pool. For your task, you should look at the following.

  • If you just need a task to run the easiest way is to use QueueUserWorkItem, which simply takes a delegate to run. The disadvantage is that you have little control over the job. The delegate can't return a value, and you don't know when the run is completed.
  • If you want a little more control, you can use the BeginInvoke/EndInvoke interface of delegates. This schedules the code to run on a thread pool thread. You can query the status via the IAsyncResult handle returned by BeginInvoke, and you can get the result (as well as any exception on the worker thread) via EndInvoke.

To use the Enter/Exit on Monitor properly, you have to make sure that Exit is always called. Therefore you should place your Exit call in a finally block.

However, if you don't need to supply a timeout value for Enter, you would be much better off just using the lock keyword, which compiles into a proper set of Enter and Exit calls.

Upvotes: 4

Neil Barnwell
Neil Barnwell

Reputation: 42165

You should look into ThreadPool.QueueUserWorkItem(). It takes a delegate that is run on the threadpool thread, passing in a state object.

i.e.

string fullname = "Neil Barnwell";
ThreadPool.QueueUserWorkItem(state =>
{
    Console.WriteLine("Hello, " + (string)state);
}, fullname);

Don't be confused by Control.BeginInvoke(). This will marshal the call to the thread that created the control, to prevent the issue where cross-thread calls update Controls. If you want simple multi-threading on a Windows form, then look into the BackgroundWorker.

Upvotes: 1

Related Questions