Reputation: 4297
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
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
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
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
Reputation: 116481
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.
Upvotes: 4
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