Tuesday, 20 August 2013

Using lock statement with ThreadPool in C#

Using lock statement with ThreadPool in C#

I have a multi-threaded program (C#) where I have to share global static
variables between threads that may take some time to execute (sending data
request to another system using WCF). The problem is that using the lock
statement does not seem to guarantee mutual exclusion when it's declared
outside of the ThreadPool.
static void Main(string[] args)
{
public static int globalVar = 0;
public object locker;
System.Timers.Timer timer1 = new System.Timers.Timer(1000);
timer1.Elapsed += new ElapsedEventHandler(onTimer1ElapsedEvent);
timer1.Interval = 1000;
timer1.Enabled = true;
System.Timers.Timer timer2 = new System.Timers.Timer(500);
timer2.Elapsed += new ElapsedEventHandler(onTimer2ElapsedEvent);
timer2.Interval = 500;
timer2.Enabled = true;
}
public void onTimer1ElapsedEvent(object source, ElapsedEventArgs e)
{
lock (locker) {
ThreadPool.QueueUserWorkItem(new WaitCallback(state =>
{
globalVar = 1;
Console.WriteLine("Timer1 var = {0}", globalVar);
}));
}
}
public void onTimer2ElapsedEvent(object source, ElapsedEventArgs e)
{
lock (locker) {
ThreadPool.QueueUserWorkItem(new WaitCallback(state =>
{
globalVar = 2;
Thread.Sleep(2000); // simulates a WCF request that may take
time
Console.WriteLine("Timer2 var = {0}", globalVar);
}));
}
}
So the lock does not work and the program can prints: Timer2 var = 1
Putting the the lock statement inside the ThreadPool seems to resolve the
problem.
public void onTimer1ElapsedEvent(object source, ElapsedEventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(state =>
{
lock (locker) {
globalVar = 1;
Console.WriteLine("Timer1 var = {0}", globalVar);
}
}));
}
public void onTimer2ElapsedEvent(object source, ElapsedEventArgs e)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(state =>
{
lock (locker) {
globalVar = 2;
Thread.Sleep(2000); // simulates a WCF request that may take
time
Console.WriteLine("Timer2 var = {0}", globalVar);
}
}));
}
However, I don't uderstand the difference between the two approaches and
why it does not produce the same behaviour.
Also, the 2nd approach resolves the mutual exclusion problem but the
timer1 thread will always have to wait for the timer2 to finish his lock
statement (which takes time), so the multi-threading concept does not work
anymore in my program. I want to know what's the best solution of having
multi threading doing their job in parallel with using shared variables ?

No comments:

Post a Comment