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 ThreadPoolですでにスケジュールされている可能性があるため、引き続き呼び出されます。

ここで明らかな何かが欠けていますか、それともモニターが想定どおりに機能しませんか?私は.NET3.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 に答える