System.Threading.Timerクラスは、内部ではThreadPool.UnsafeQueueUserWorkItem()でスレッドが実行されます。QueueTimerCompletion - timer.cs
.NET Frameworkにはこれと同名のTimerクラスが4つあるため、名前空間に注意します。
Visual StudioのデザイナにあるタイマーはSystem.Windows.Forms.Timerであり、ここで解説するSystem.Threading.Timerとは異なります。このクラスはすべての処理を1つのスレッドで行うため、複数のタイマを同時に実行できません。
Visual Studioのツールボックス
public Timer( TimerCallback callback, // 実行するコールバック メソッド Object state, // callbackへ渡すデータ int dueTime, // callbackが呼び出されるまでの遅延時間 [msec] int period // callbackが呼び出される周期 [msec] )Timer(TimerCallback, Object, Int32, Int32) - Timer コンストラクター (System.Threading) | Microsoft Learn
指定時間に呼び出されるコールバックは引数のcallbackで、TimerCallbackデリゲートの形式で指定します。
delegate void TimerCallback( Object state )TimerCallback 代理人 (System.Threading) | Microsoft Learn
dueTimeとperiodで、callbackの呼び出し方法を指定できます。
すぐにタイマーを開始しないならばTimer(TimerCallback)のコンストラクタでオブジェクトを生成し、後からChange()でdueTimeとperiodを指定する方法もあります。ただしこのコンストラクタではコールバックへ渡すデータを指定できず、Timerオブジェクト自身がstateオブジェクトとして渡されます。
void Main()
{
System.Threading.Timer timer
= new System.Threading.Timer( Method, null, 100, 200 );
}
void Method( Object state )
{
// このメソッドが制御を戻すと、スレッドはスレッドプールに戻り次のタスクを待つ
}
これはラムダ式を用いると、次のようにも記述できます。
System.Threading.Timer timer = new System.Threading.Timer((state) =>
{
// 別スレッドでの処理
}, null, 100, 200);
public bool Change( int dueTime, // 遅延時間 [msec] int period // 呼び出し周期 [msec] )Change(Int32, Int32) - Timer.Change メソッド (System.Threading) | Microsoft Learn
引数 | 値 | 作用 |
---|---|---|
dueTime | 0 | コールバックをすぐに呼び出す (タイマーをすぐに再開する) |
Timeout.Infinite | コールバックを呼び出さない (タイマーを停止する)
これ以降コールバックを呼び出さないのであって、すでに呼び出したコールバックが停止するわけではない |
|
period | 0 または Timeout.Infinite | 周期的な呼び出しを無効にする |
タイマーを確実に破棄するには、引数でWaitHandleを受け取るDispose()を呼びます。multithreading - c# System.Threading.Timer wait for dispose - Stack Overflow
public bool Dispose ( System.Threading.WaitHandle notifyObject );Dispose(WaitHandle) - Timer.Dispose Method (System.Threading) | Microsoft Learn
using (System.Threading.WaitHandle waitHandle = new System.Threading.ManualResetEvent(false)) { if (timer.Dispose(waitHandle)) { // まだ破棄されていないならば、破棄されるのを待つ const int millisecondsTimeout = 1000; if (!waitHandle.WaitOne(millisecondsTimeout)) { // 指定時間内に破棄されなかった } } }