スレッド (Thread)

非同期処理には、次の3つの方法があります。

  1. スレッドプールを使用する
  2. 専用のスレッドを作成する
  3. タイマーで定期的に実行する

参考書

スレッドプール (バックグラウンド スレッド) - ThreadPoolクラス

スレッドプールにキューを置くには、QueueUserWorkItemメソッドを使用します。callback引数で渡したメソッドは、スレッドプールのスレッドが使用可能になったときに実行されます。

QueueUserWorkItemメソッドには2つの形式があり、state引数を取らない方はコールバックのメソッドにnullを渡すことになります。

public static bool QueueUserWorkItem(
    WaitCallback callBack,   // 実行するメソッド
    Object state             // メソッドへ渡すデータ
)
public static bool QueueUserWorkItem(
    WaitCallback callBack   // 実行するメソッド
    )
ThreadPool メンバ (System.Threading) - MSDN

スレッドで実行されるメソッドの形式 (WaitCallbackデリゲート)

スレッドで実行するメソッドはWaitCallbackデリゲート型である必要があり、次の形式となります。

delegate void WaitCallback( Object state )

サンプルコード

void Main()
{
    System.Threading.ThreadPool.QueueUserWorkItem(MethodName );
}

void MethodName( Object state )
{
    // このメソッドが制御を戻すと、スレッドはスレッドプールに戻り次のタスクを待つ
}

このコードはC#の匿名メソッド (Anonymous Methods) を用いることで、次のように記述することもできます。

void Main()
{
    System.Threading.ThreadPool.QueueUserWorkItem(
        delegate( Object state )
        {
            // ここでスレッドの処理をする
        }
        );
}

専用のスレッド (フォアグラウンド スレッド) - Threadクラス

スレッドプールを使用せずに専用のスレッドを作成する場合には、フォアグラウンド スレッドを使用します。このスレッドでは処理の優先度を変更したり、スレッドが処理を完了する前にアプリケーションが終了されてしまうのを防ぐことができます。

IsBackgroundプロパティをtrueとすることで、バックグラウンド スレッドとして動作させることもできます。

public Thread( ParameterizedThreadStart start )

スレッドで実行されるメソッドの形式 (ParameterizedThreadStartデリゲート)

スレッドで実行するメソッドはParameterizedThreadStartデリゲート型ですが、これはWaitCallbackデリゲートと同一の形式を持ちます。

delegate void ParameterizedThreadStart( Object obj )

スレッドの起動

スレッドを開始するには、Startメソッドを実行します。

public void Start()
Thread メンバ (System.Threading) - MSDN

サンプルコード

void Main()
{
    System.Threading.Thread thread = new System.Threading.Thread( MethodName );

    // スレッドを起動する
    thread.Start();
}

void MethodName( Object state )
{
    // このメソッドが制御を戻すと、スレッドは破棄される
}

タイマーによる定期的な実行 - Timerクラス

このクラスは、内部ではSystem.Threading.ThreadPoolクラスのQueueUserWorkItemメソッドを呼び出してスレッドを実行します。

public Timer(
    TimerCallback callback,  // 実行するメソッド
    Object state,            // メソッドへ渡すデータ
    int dueTime,             // メソッドが呼び出されるまでの遅延時間 [msec]
    int period               // メソッドが呼び出される周期 [msec]
    )

スレッドで実行されるメソッドの形式 (TimerCallbackデリゲート)

delegate void TimerCallback( Object state )

遅延時間と周期の変更

遅延時間と周期はChangeメソッドで変更できます。

public bool Change(
    int dueTime,
    int period
)

サンプルコード

void Main()
{
    System.Threading.Timer timer = new System.Threading.Timer( MethodName, null, 100, 200 );
}

void MethodName( Object state )
{
    // このメソッドが制御を戻すと、スレッドはスレッドプールに戻り次のタスクを待つ
}

Visual Studioのタイマー

Visual Studioのデザイナにあるタイマーは、System.Windows.Forms.Timerクラスになります。このクラスはすべての処理を1つのスレッドで行うため、複数のタイマを使用して同時に実行することはできません。

Timerコントロール
Visual Studioのツールボックス

用語解説

スレッドプールとはアプリケーションから利用できる一群のスレッドのことであり、そこで処理されるスレッドには以下の2種類があります。

ワーカースレッド
アプリケーションがスレッドプールに対して、非同期の計算処理を要求したときに利用される
I/Oスレッド
非同期I/O処理が完了したことを、アプリケーションに伝えるきにされる

非同期プログラミングモデル : APM (Asynchronous Programming Model)