プログラム

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

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

全て表示する >

【C#プログラミングレッスン】 No.150-AutoResetEvent(2)

2007/12/11

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

今回は、スレッド間のデータ受け渡しについて説明します。
スレッドの同期については、前回同様AutoResetEventクラスを使っています。


■──────────────────────────────────
■ スレッド間のデータ受け渡し

前回のコードを少し変更し、スレッドに値渡し、スレッドからの結果を受け取
るようにしてみました。

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

class Program {
    static void Main(string[] args) {
        Console.WriteLine("2つの処理を開始");
        MyWorker worker1 = new MyWorker("Hoo");
        worker1.Execute(7);
        MyWorker worker2 = new MyWorker("Bar");
        worker2.Execute(30);

        worker1.Wait();
        worker2.Wait();
        Console.WriteLine("2つの処理を完了");
        Console.WriteLine(worker1.Result.ToString());
        Console.WriteLine(worker2.Result.ToString());

        Console.ReadLine();
    }
}

class MyWorker {
    private BackgroundWorker _worker = new BackgroundWorker();
    private string _name;
    private AutoResetEvent _are = new AutoResetEvent(false);
    private long _result;

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

    public bool Execute(int n) {
        _worker.RunWorkerAsync(n);
        return true;
    }

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

    public long Result {
        get { return this._result; }
    }

    private void worker_RunWorkerCompleted(object sender, 
                                     RunWorkerCompletedEventArgs e) {
        if ( !e.Cancelled && e.Error == null ) {
            this._result = (long)e.Result;
        }
        Console.Write(_name + "終了 ");
        _are.Set();
    }

    private void worker_DoWork(object sender, DoWorkEventArgs e) {
        int count = (int)e.Argument;
        long a = 1;
        long b = 1;
        long c = 1;
        for ( int i = 3; i <= count; i++ ) {
            c = a + b;
            a = b;
            b = c; 
        }
        System.Threading.Thread.Sleep(2000);  // デモ用・本来は不要
        e.Result = c;
    }
}

前回までのコードとの違いだけを説明します。

●引数を受け取る

Executeメソッドで受け取った引数は、RunWorkerAsyncメソッドにそのまま
受け渡しています。
この値は、worker_DoWorkメソッドの引数 DoWorkEventArgs e の Argument
プロパティに格納されていますので、

 int count = (int)e.Argument;

の行で、引数を取り出しています。


●結果を受け取る

worker_DoWorkメソッドで計算した値は、

 e.Result = c;

でResultプロパティに格納しています。
この値を、呼び出し側から参照できるように、MyWorkerクラスに、

    public long Result {
        get { return this._result; }
    }

と、Resultプロパティを作成しています。
Mainメソッドでは、このResultプロパティを参照することで、計算結果を
取得することができます。
もちろん、Wait() メソッドを呼び出してからでないと、有効な値を取得する
ことはできません。

場合によっては、
    public long Result {
        get {
            _are.WaitOne();
      _are.Set();   // (*)
            return this._result;
        }
    }

として、Waitメソッドを呼び出す必要がない設計にすることも有りかもしれま
せん。
(*)の行があるのは、WaitOne()で、シグナル状態になるまで待つと、自動的に、
Resetされてしまう(つまり、非シグナル状態になってしまう)ため、再度、
シグナル状態にするためです。この行がないと、同じ、MyWorkerオブジェクト
に対し、複数回、Resultプロパティを参照することができなくなります。

┌─┬─────────────────────────┬─┬─┬─┐
│☆│ 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!: 非表示   

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

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

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

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

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