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)
残念ながら、まだオプションではありません。