*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

<C#  IAsyncResult 使用の非同期処理搭載クラスの作成>

AsyncWaitHandle を使用して、アプリケーション実行を指定時間ブロック


*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*


スレッド作成における一連の説明(知恵ノート)において、ここでは、

 

「<C#> AsyncWaitHandle を使用して、アプリケーション実行を指定時間ブロック」

 

について説明します。






総合の目次


本ページを含めた関連事項の総合目次です。

http://note.chiebukuro.yahoo.co.jp/detail/n153114






はじめに


スレッド(非同期処理)の処理結果を待っている間に、他の作業を行うことができないようにするアプリケーションがあります。
そのような仕様にしたい場合は、スレッド(非同期処理)が完了するまで、アプリケーション実行のブロックする必要があります。
ここでは、AsyncWaitHandle プロパティでスレッド終了を指定時間待機することにより、アプリケーション実行をブロックする方法を紹介します。


 

なお、本サンプルでは、スレッドで処理するコードをクラス化しています。
そのクラスは、IAsyncResultを実装したクラスとします。



特徴


他の関連サンプル(スレッドの一連のサンプル)と比較した本サンプルの特徴を以下に記します。


<スレッドが完了するまで、アプリケーション実行のブロックするか、しないか>
 ---> アプリケーション実行をブロックする。


<ブロックのやり取りの方法>
 ---> BeginInvoke メソッドによって返される IAsyncResult の AsyncWaitHandle プロパティを使用してブロックする。





サンプルコード


ここで取り上げるサンプルは、なるべく複雑にならない範囲で、実際にスレッドの作り方を確かめられるものとします。






本サンプの仕様


本サンプルでは、スレッド生成等の基本的なコードの書き方を紹介することが目的なので、単純な計算(足し算)をして、その計算結果をテキストボックスに表示するだけにしました。
具体的には、まず、テキストボックス textBox1 に、ユーザーが演算値1(例えば、7+12 ならば、7の方の値)を入力します。
次に、テキストボックス textBox2 に、ユーザーが演算値2(7+12 の12の方の値)を入力します。
次に、ボタン button1 をクリックすると、上記の入力値から、計算(足し算)を行ないます。
ここで、その計算処理は、スレッドを用意して、そのスレッドで計算をします。
次に、計算結果をテキストボックス textBox3 に表示します。




フォームデザイン等の前準備


コードを記述する前に、フォームのデザイン作成などの、以下の前準備を行なって下さい。


<プロジェクトの作成>
本サンプルの確認用に、新規にプロジェクトを作成して下さい。
プロジェクトの種類は、「Windowsフォームアプリケーション」です。


<フォームのデザイン>
デザイン画面で、TextBox (テキストボックス) を3個と、 Button (ボタン)を1個貼り付けて下さい。

 

 デザイン画面



<テキストボックスの複数行化>

テキストボックスは、デフォルトでは1行用になっています。
textBox1 と textBox2 は、デフォルト(1行表示用)のままで構いません。
しかし、textBox3 については、複数行の文字を扱いたいので、以下の操作で、テキストボックスを複数行対応にして下さい。
まず、先程貼り付けたテキストボックス textBox3 を選択状態にして下さい(すなわち、デザイン画面上のテキストボックス textBox3 をクリックする)。
そうすると、テキストボックスの右上に、小さな三角形のマークが表示されます。
それをクリックすると Multiline と言う表記のチェックボックスが表示されます。
そのチェックボックスにチェックを入れると、複数行対応になります。
あとは、デザイン画面のチェックボックスをマウス操作で、縦幅を広げて下さい。




テキストボックス三角

 


<イベントプロシージャの作成>

デザイン画面のフォームをダブルクリックして、Form1_Load() メソッドを作って下さい。

また、先程貼り付けたデザイン画面上のボタン「button1」をダブルクリックして、button1_Click() メソッド を作って下さい。



<クラスを書くためのソースファイルの作成>


[プロジェクト] - [クラスの追加] で、「新しい項目の追加」画面を表示する。
その画面の [ファイル名]欄に任意のファイル名(クラス用ソースファイルのファイル名)を記入する。
[追加]ボタンをクリックする。

 

なお、ここで作成されたソースファイルには、後述しますクラスのコード(「演算クラスのコード」のコード)を記述します。



 

演算クラスのコード


http://note.chiebukuro.yahoo.co.jp/detail/n160546

 

 

(記述量上限の制限で、別のページに記述しています)

 

 

 

Formクラスのコード



 

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;


// <IAsyncResult 使用の非同期処理搭載クラスの作成>
// AsyncWaitHandle を使用して、アプリケーション実行を指定時間ブロック
namespace SimpleSampleToCallByAsynchronousThread_04
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();


            // スレッドからテキストボックスをアクセスすることを指定
            Control.CheckForIllegalCrossThreadCalls = false;
        }


        //============
        // メンバー変数


        // 計算スレッドクラス
        CommonProcessing.ArithmeticThreadClass ArithmeticObj;

 

        //============
        // フォーム起動時イベント
        private void Form1_Load(object sender, EventArgs e)
        {

            // 計算スレッドクラスの生成
            ArithmeticObj = new CommonProcessing.ArithmeticThreadClass();


            // 演算値を初期設定
            textBox1.Text = "7";
            textBox2.Text = "12";


            // コントロール初期化
            button1.Text = "計算開始";

        }

 

        //============
        // 計算処理スレッド開始用ボタン
        private void button1_Click(object sender, EventArgs e)
        {

            // ユーザー入力された演算値(string型)を数値(float型)に変換
            float data1, data2; // 演算値1、2
            float.TryParse(textBox1.Text, out data1); // 演算値1
            float.TryParse(textBox2.Text, out data2); // 演算値2


            // スレッドを起動し、計算処理スレッド用メソッドを実行します。
            IAsyncResult AsyRes = ArithmeticObj.BeginAdd(data1, data2, null);


            // 非同期処理の完了を指定時間だけ待つ。
            // (指定時間の単位はミリ秒)
            AsyRes.AsyncWaitHandle.WaitOne(3000);


            // 非同期処理が完了しているのかポーリング(調査)を行なう。
            // 非同期処理が完了している場合
            if (AsyRes.IsCompleted == true)
            {

                // EndInvoke()メソッドで、スレッドの完了処理を実行。
                // 及びワーカースレッドでの処理結果の受け取り。
                // ワーカースレッドの処理が完了するまで、 EndInvoke メソッドはブロックする。
                float result = ArithmeticObj.EndAdd(AsyRes);


                // 計算結果表示
                textBox3.Text += data1.ToString() + " + " + data2.ToString() + " = " + result.ToString() + " ";

            }
            // 非同期処理が完了していない場合
            else
            {
                textBox3.Text += "指定時間だけ待ちましたが、計算は完了しませんでした。 ";
            }

        }


    }
}




 

実行結果


計算結果が表示されます。

 

なお、本サンプルでは、わざと計算時間がかかるようにしていますので、注意して下さい。

その時間をかかるようにしたコードのパラメーターを可変して、計算時間を調整してみて下さい。

 

 


実行結果待ち時間よりも計算時間が短かった場合

 

 

 

 

 

 

 実行結果2計算時間よりも待ち時間が短かった場合



さいごに


特になし。