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?
A thread pool reuses previously created threads to execute current tasks and offers a solution to the problem of thread cycle overhead and resource thrashing. Since the thread is already existing when the request arrives, the delay introduced by thread creation is eliminated, making the application more responsive.
Thread pool in C# is a collection of threads. It is used to perform tasks in the background. When a thread completes a task, it is sent to the queue wherein all the waiting threads are present. This is done so that it can be reused.
Java Thread pool represents a group of worker threads that are waiting for the job and reused many times. In the case of a thread pool, a group of fixed-size threads is created. A thread from the thread pool is pulled out and assigned a job by the service provider.
You can wait for a task to finish in a ThreadPoolExecutor by calling the wait() module function.
There are a couple of ways to use the thread pool. For your task, you should look at the following.
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. 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.
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));
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With