3

我正在使用 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 线程池上。

我是否在这里遗漏了一些明显的东西,或者 Monitor 没有按预期工作?我在 .NET 3.5 上,所以

Monitor.TryEnter(myLock,hasLock)

不幸的是,这还不是一个选择。

4

1 回答 1

8

Monitor.TryEnter()方法返回一个布尔值,您忽略它。当您尝试退出您从未真正进入的锁时,您看到的错误就会发生。

快速修复您当前的代码:

//Monitor.TryEnter(myLock);
if (! Monitor.TryEnter(myLock)) return;
于 2013-01-17T12:03:01.420 回答