我正在使用Threading.Timer在我的应用程序中运行消息泵。
有时,所需的工作时间比计时器的时间间隔要长,我需要将代码“跳过”。
我写了一个小测试应用程序进行测试,并在锁定时继续遇到SynchronizationLockException:
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);
}
}
我现在无法回想起这个链接,但是我通过在回调函数的开始和结束时禁用和启用计时器找到了我的初始要求的建议解决方案,但是由于文档说明在计时器之后停了它可以 仍然被调用,因为它已经可以在.NET ThreadPool上安排。
我是否遗漏了一些明显的东西,或者监视器不能正常工作? 我在.NET 3.5上,所以
Monitor.TryEnter(myLock,hasLock)
遗憾的是还不是一个选择。
答案 0 :(得分:8)
Monitor.TryEnter()
方法返回一个布尔值,你忽略它。当您尝试退出从未真正输入的锁定时,您会看到错误。
快速修复当前代码:
//Monitor.TryEnter(myLock);
if (! Monitor.TryEnter(myLock)) return;