メインスレット(フォーム)がサブスレッドを生成し、そのサブスレッドがタイマースレッドを作ります。
タイマーにより処理を行った内容をサブスレッドが受け取り、その内容をメインスレッド(Form)が受け表示する例です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace strudy_deligate { public partial class プロセスOFFONForm : Form { private メイン処理スレッド メイン処理スレッド; public プロセスOFFONForm() { InitializeComponent(); } private void プロセスOFFONForm_Load(object sender, EventArgs e) { メイン処理スレッド = new メイン処理スレッド();//メイン処理の生成 //コールバック先の定義・・・イベントハンドラの追加 メイン処理スレッド.タイマスレッド.タイマイベント発生.メイン発生メソッド += new イベント発生クラス.メインイベント(this.イベント受信処理); } private void btn開始_Click(object sender, EventArgs e) { //メイン処理スレッドの生成(無限ループ) Task t1 = Task.Run(() => メイン処理スレッド.スレッドスタート());//4.5以降での対応 } private void btn終了_Click(object sender, EventArgs e) { } //コールバック private void イベント受信処理(string proc, string message)//コールバック { Console.WriteLine("イベント受信処理-MAIN proc =" + proc + "message" + message); //処理-1 テキストエリア表示(proc, message); } /// <summary> /// 別スレッドからのメッセージをテキストエリアへ表示 /// invokeを利用する /// </summary> /// <param name="proc"></param> /// <param name="message"></param> private void テキストエリア表示(string proc, string message) { if (this.InvokeRequired)//Invokeする必要があるかを判定 { //必要ならばInvokeメソッドとMethodInvokerデリゲートを利用してFormがデUIデータ処理できる様にする。 this.Invoke((MethodInvoker)delegate () { テキストエリア表示(proc, message); });//自身の関数に再帰させるだけで処理ができる様になるおまじない。 return; } else//最終的に、ここにデータを流しFormへ表示する。 { this.textステータス.AppendText("proc=" + proc + "message=" + message);//結果表示 } } } /// <summary> /// タイマーを実行してタイマーからの戻りをメインフォームへ伝える /// </summary> public class メイン処理スレッド { public タイマスレッド タイマスレッド; public メイン処理スレッド()//コンストラクタ { タイマスレッド = new タイマスレッド();//タイマスレッド起動 //コールバック先の定義・・・イベントハンドラの追加 //下記の様に書いてOK //タイマスレッド.タイマイベント発生.タイマ発生メソッド1 += タイマイベント発生_タイマ発生メソッド1; // : //タイマスレッド.タイマイベント発生.タイマ発生メソッド4 += タイマイベント発生_タイマ発生メソッド4; // or 下記 タイマスレッド.タイマイベント発生.タイマ発生メソッド1 += new イベント発生クラス.タイマイベント(this.イベント受信処理1); タイマスレッド.タイマイベント発生.タイマ発生メソッド2 += new イベント発生クラス.タイマイベント(this.イベント受信処理2); タイマスレッド.タイマイベント発生.タイマ発生メソッド3 += new イベント発生クラス.タイマイベント(this.イベント受信処理3); タイマスレッド.タイマイベント発生.タイマ発生メソッド4 += new イベント発生クラス.タイマイベント(this.イベント受信処理4); } public void スレッドスタート() { タイマスレッド.タイマスレッドスタート();//タイマースレッドを開始(無限ループ) } //以下、タイマスレッドからのコールバック関数 private void タイマイベント発生_タイマ発生メソッド1(int number, string message) { Console.WriteLine("処理-1 num =" + number.ToString() + "message" + message); //処理-1 //throw new NotImplementedException(); } private void タイマイベント発生_タイマ発生メソッド4(int number, string message) { Console.WriteLine("処理-4 num =" + number.ToString() + "message" + message); //処理-1 //throw new NotImplementedException(); } private void イベント受信処理1(int num, string message)//コールバック { Console.WriteLine("イベント受信処理-1 num =" + num.ToString() + "message" + message); //処理-1 イベントをメインへ表示(num, message); } private void イベント受信処理2(int num, string message)//コールバック { Console.WriteLine("イベント受信処理-2 num =" + num.ToString() + "message" + message); //処理-2 イベントをメインへ表示(num, message); } private void イベント受信処理3(int num, string message)//コールバック { Console.WriteLine("イベント受信処理-3 num =" + num.ToString() + "message" + message);//処理-3 イベントをメインへ表示(num, message); } private void イベント受信処理4(int num, string message)//コールバック { Console.WriteLine("イベント受信処理-4 num =" + num.ToString() + "message" + message);//処理-4 イベントをメインへ表示(num, message); } private void イベントをメインへ表示(int num, string message) { //リターンメインイベント リターンメインイベント = new リターンメインイベント(); タイマスレッド.タイマイベント発生.処理発生(num.ToString(), message); } } /// <summary> /// タイマスレッドクラス /// </summary> public class タイマスレッド { public イベント発生クラス タイマイベント発生;//別クラスより参照できる様にpublicとする public System.Timers.Timer timer; private int i; public タイマスレッド() { タイマイベント発生 = new イベント発生クラス(); } public void タイマスレッドスタート() { // タイマーイベントで定期的にイベントを発生させる timer = new System.Timers.Timer(1000);//1秒毎wait timer.Enabled = true;//タイマーイベント・スタート timer.Elapsed += (sender, e) =>//タイマーイベントの受信 { DateTime dt = DateTime.Now; i++; string si = i.ToString(); string sd = dt.ToString("yyyy/MM/dd (ddd) HH:mm:ss" + "\n"); //Console.WriteLine("i =" + si + "sd=" + sd); //以下、タイマーイベントの条件により各種のイベントを発生させます タイマイベント発生.タイマ発生1(i, sd); }; } } /// <summary> /// イベントを発生させるクラス /// </summary> public class イベント発生クラス { //タイマからのイベント発生要求 //デリゲートの宣言:戻り値無しで引数をint型、string型とする。 public delegate void タイマイベント(int number, string message); //ここでは"イベントハンドラ"という「イベントデリゲート」を宣言する public event タイマイベント タイマ発生メソッド1;//発生メソッドの実体をコールするとイベントが発生する事になります。 public event タイマイベント タイマ発生メソッド2;//発生メソッドの実体をコールするとイベントが発生する事になります。 public event タイマイベント タイマ発生メソッド3;//発生メソッドの実体をコールするとイベントが発生する事になります。 public event タイマイベント タイマ発生メソッド4;//発生メソッドの実体をコールするとイベントが発生する事になります。 public void タイマ発生1(int num, string message)//イベント発生メソッド { タイマ発生メソッド1(num, message);//イベントの発生 } public void タイマ発生2(int num, string message)//イベント発生メソッド { タイマ発生メソッド2(num, message);//イベントの発生 } public void タイマ発生3(int num, string message)//イベント発生メソッド { タイマ発生メソッド3(num, message);//イベントの発生 } public void タイマ発生4(int num, string message)//イベント発生メソッド { タイマ発生メソッド4(num, message);//イベントの発生 } //メイン処理スレッドからのイベント発生要求 //デリゲートの宣言:戻り値無しで引数をstrin型、string型とする。 public delegate void メインイベント(string proc, string message); //ここでは"イベントハンドラ"という「イベントデリゲート」を宣言する public event メインイベント メイン発生メソッド;//発生メソッドの実体をコールするとイベントが発生する事になります。 public void 処理発生(string proc, string message)//イベント発生メソッド { メイン発生メソッド(proc, message);//イベントの発生 } } } |
4つのクラスから構成されます。
メインスレッド・・・フォームです。メイン処理スレッドを生成して、それからのイベントを受け取り、テキストボックス(マルチライン)へ表示します。
メイン処理スレッド・・・タイマースレッドを生成して、それからのイベントを受け取り、応じた処理を行い、行った処理の完了イベントを発生させ、メインスレッドに処理させます。
タイマースレッド・・・時刻条件によりイベントを発生させ、その処理をメイン処理スレッドに行わせます。
イベント発生クラス・・・イベントを発生させます。実体化させる場所がタイマースレッド内というのが気になります。
と言うのも、ボタン押下でメイン処理スレッドが複数作られます。耐えられるのでしょうか?