プログラム

C#プログラミングレッスン

C#での .NETプログラミングを易しく丁寧に解説するメールマガジンです。「C#プログラミング・レッスン」で、.NETプログラミングをマスターしましょう。

全て表示する >

【C#プログラミングレッスン】 No.149-AutoResetEvent

2007/12/04

┏━┳━━━━━━━━━━━━━━━━━━━━━━━━━┳━┳━┳━┓
┃☆┃ C#プログラミングレッスン                         ┃_┃□┃×┃
┣━┻━━━━━━━━━━━━━━━━━━━━━━━━━┻━┻━┻━┫
┃ AutoResetEvent                                             No.149┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

■──────────────────────────────────
■ AutoResetEventを使った同期処理

No145「BackgroundWorker(3)」の最後に書いた。
「Mainメソッドで2つのスレッドが終了するまで待つにはどうすれば良いのだ
  ろうか」
「その結果を受け取る方法は」
「2つのワーカースレッドで同じ変数にアクセスするにはどうすれば良いのだ
  ろうか」

といった、疑問にまだお答していませんでしたので、再度、BackgroundWorker
の例に戻り、これらの疑問にお答えしたいと思います。

今回は、スレッドが終了するまで待つ方法についてみていきます。
では、早速、以下のコードを実行してみてください。
worker1, worker2 の2つが終了するのを待っていることを確認できると思い
ます。

using System;
using System.ComponentModel;
using System.Threading;

class Program {
    static void Main(string[] args) {
        MyWorker worker1 = new MyWorker("Hoo");
        worker1.Execute();
        MyWorker worker2 = new MyWorker("Bar");
        worker2.Execute();

        Console.WriteLine("2つの処理を待機します。");
        worker1.Wait();
        worker2.Wait();
        Console.WriteLine("\n2つの処理を完了");
        Console.ReadLine();
    }
}

class MyWorker {
    private BackgroundWorker worker = new BackgroundWorker();
    private string name;
    private AutoResetEvent are = new AutoResetEvent(false);

    public MyWorker(string name) {
        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
        worker.RunWorkerCompleted += new 
            RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
        this.name = name;
    }

    public bool Execute() {
        worker.RunWorkerAsync();
        return true;
    }

    public void Wait() {
        are.WaitOne();
    }

    private void worker_RunWorkerCompleted(object sender, 
                                      RunWorkerCompletedEventArgs e) {
        Console.Write(name + "終了 ");
        are.Set();
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e) {
        for ( int i = 0; i < 50; i++ ) {
            Console.Write(name + i.ToString() + " ");
            System.Threading.Thread.Sleep(100);
        }
    }
}


No145で示したコードとの違いは、MyWorkerに、AutoResetEventクラスを使い、
Waitというメソッドを追加したことです。

AutoResetEventのWaitOne() メソッドは、AutoResetEvent.Set()メソッドが呼
ばれるまで(シグナル状態になるまで)待機します。
この例では、AutoResetEventのコンストラクタでfalseを渡していますので、
初期状態は、非シグナル状態です。

Mainメソッドでは、MyWorker.Execute() メソッドを呼び出しますが、すぐに
Execute()から復帰し、MyWorker.Wait()メソッドで待機状態になります。

一方、Executeメソッドは、スレッドを起動し、worker_DoWorkを呼び出します。
worker_DoWorkメソッドが終了すると、worker_RunWorkerCompletedメソッドが
呼ばれ、そこで、AutoResetEvent.Set()メソッドを呼び出し、シグナル状態に
しています。

シグナル状態になると、Mainメソッドでは、MyWorker.Wait() から制御が戻り、
"2つの処理を完了" という文字列をコンソールに出力します。

┌─┬─────────────────────────┬─┬─┬─┐
│☆│ C#プログラミングレッスン  (ぼぼ週刊)            │_│□│×│
├─┴─────────────────────────┴─┴─┴─┤
│ Published by Gushwell.                                           │
│ Copyright (C) 2004-2007 Gushwell All rights reserved.            │
│ Microsoft MVP Visual Developer - Visual C#(Apr 2005 - Mar 2008)  │
│-------------------- Gushwell's Page ---------------------------- │
│ 窓際プログラマーの独り言  :http://blog.livedoor.jp/gushwell/    │
│ 窓際プログラマーの読書三昧:http://gushwell.jugem.jp/            │
│ Gushwell's C# Programing Page:http://gushwell.ifdef.jp/         │
│ C#デザインパターン :                                             │
│  『増補改訂版Java言語で学ぶデザインパターン入門 / 結城 浩(著)』  │
│   のサンプルコードをC#に移植したものを掲載しています。           │
│   移植後のコードの公開は、結城氏の了解を得ています。             │
│   http://blog.livedoor.jp/gushwell/archives/50333227.html        │
└─────────────────────────────────┘

規約に同意してこのメルマガに登録/解除する

メルマガ情報

創刊日:2004-08-12  
最終発行日:  
発行周期:ほぼ週刊  
Score!: 非表示   

コメント一覧コメントを書く

この記事にコメントを書く

上の画像で表示されている文字を半角英数で入力してください。

※コメントの内容はこのページに公開されます。発行者さんだけが閲覧できるものではありません。 コメントの投稿時は投稿者規約への同意が必要です。

  • コメントはありません。