Reputation: 1828
I am using a Threading.Timer to run the message pump in my application.
Sometimes the work in required takes longer than the intervals between the timer's intervals, and I need the code to then be 'skipped'.
I wrote a little test app to test, and keep running into a SynchronizationLockException on my locking:
static void Main(string[] args)
{Program t = new Program();
System.Threading.Timer myTimer = new Timer(t.Tick,null,1000,1000);
Thread.Sleep(10000);
myTimer.Change(0,0);
Console.WriteLine("Waiting on lock in main thread...");
Monitor.Enter(t.myLock);
Console.WriteLine("Done");
Monitor.Exit(t.myLock);
}
public readonly Object myLock = new Object();
public void Tick(object state)
{
Console.WriteLine("Acquiring lock! From thread " + Thread.CurrentThread.ManagedThreadId);
Monitor.TryEnter(myLock);
try
{
Thread.Sleep(6000);
Console.WriteLine("Inside workload!From thread " + Thread.CurrentThread.ManagedThreadId);
}
finally
{
Console.WriteLine("Releasing lock!From thread " + Thread.CurrentThread.ManagedThreadId);
Monitor.Exit(myLock);
}
}
I can't recall the link now, but I have found a suggested solution to my initial requirement by disabling and enabling the timer at the start and end of the Callback function, but since the documentation states that after the timer has been stopped it can still be called since it could already have been scheduled on the .NET ThreadPool.
Am I missing something obvious here or does Monitor not work as it is supposed to? I am on .NET 3.5, so
Monitor.TryEnter(myLock,hasLock)
is unfortunately not yet an option.
Upvotes: 3
Views: 4272
Reputation: 273274
The Monitor.TryEnter()
method returns a boolean, you are ignoring it. The error you see happens when you try to Exit a lock you never really Entered.
A quick fix for your current code:
//Monitor.TryEnter(myLock);
if (! Monitor.TryEnter(myLock)) return;
Upvotes: 8