3

2 つのタイマー( System.Timers.Timer ) が実行されており、両方のタイマー Elapsed-Events でデリゲートがサブスクライブしています。両方のメソッド (サブスクライブされたデリゲート内) は、同じオブジェクト (リストとリスト内のオブジェクトなど) で動作しています。

タイマー Elapsed-Events が同時に呼び出されたとします。

デリゲートは異なるスレッドで実行されますか? それとも次々と呼び出されるのでしょうか?コードをスレッド セーフにし、ロックを使用する必要がありますか?

4

3 に答える 3

3

System.Windows.Forms.TimerではなくSystem.Timers.Timerを参照していると思います。ドキュメントが言うように:

サーバーベースのタイマーは、マルチスレッド環境でワーカー スレッドを使用するように設計されています。サーバー タイマーは、発生した Elapsed イベントを処理するためにスレッド間を移動できるため、Windows タイマーよりも正確にイベントを時間通りに発生させることができます。

Elapsed2 つの異なるスレッドが2 つの異なるタイマーのイベントを発生させないという保証はありません。コードをスレッドセーフにすることをお勧めします。

Elapsedの複数のコールバックを同時に呼び出すことができることを示す短いコード スニペットを追加しています(この場合、デッドロックが発生しDebug.WriteLineます。呼び出されることはありません)。

var _lock = new object();
GC.KeepAlive(_lock);
var timer1 = new Timer(100);
var timer2 = new Timer(200);
timer1.Elapsed += delegate
{
    lock (_lock)
        Thread.Sleep(-1);
};
timer2.Elapsed += delegate
{
    lock (_lock)
        Debug.WriteLine("Hello world.");
};
timer1.Start();
timer2.Start();
于 2012-12-28T17:14:07.683 に答える
1

これらは ThreadPool のワークアイテムとしてキューに入れられるため、同時に実行されるリスクがあります。これが起こらないようにする 1 つの方法は、単一のタイマー コールバックと反復時間を無限にスケジュールするだけで(System.Threading.Timerこれをサポートします)、作業が完了したときに再スケジュールすることです。

于 2012-12-28T17:14:07.703 に答える
1

タイマー コールバック (特定のクラス/名前空間を指定しない) は、常に別のスレッドで呼び出されます。したがって、コードをスレッドセーフにする必要があります。それらが「同時に」呼び出されるか、その後コース外で呼び出されるかは、設定​​された間隔によって異なります。
同じ間隔が設定されている場合、どのコールバックが最初に呼び出されるかは、ほとんど決定論的ではありません。

于 2012-12-28T17:16:10.070 に答える