C# - よく使うクラス - System.Windows.Forms - Control.Invoke

クラウディア 
1. 概要
2. System.InvalidOperationException
3. Invoke()

1. 概要

 「Control」というのは、偉大なる「Microsoft」さまによれば。
視覚的に表現されるコンポーネントであるコントロールの基本クラスを定義します。
 ちゅうことなのですが、コントロールの基本クラスなのであります。  で、ここでは、「Control.Invoke()」メソッドについてメモするのですが、ちょっとややこしい処理を行おうとすると必須になってきます。  本ページは、下記のサイトを参考にさせていただきました。
Control.Invoke メソッド (System.Windows.Forms) 」
「【C#】解決策|有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール がアクセスされました

2. System.InvalidOperationException

 およそ、こんなダイアログがあるとして・・・。  「開始」を押したら、「開始」ボタンが非活性化しまして、「停止」ボタンが活性化。
「C#」-「ダイアログ」

 「開始」と同時に、タイマを起動して、「停止」ボタンが押されるか、タイマがタイムアウトしたら、停止するということで。
 「停止」ボタン押下時のイベント処理が。


private void button2_Click(object? sender, EventArgs e)
{
	if (timer != null)
	{
		timer.Dispose();
		timer = null;
	}

	button1.Enabled = true;
	button2.Enabled = false;
}
 となっちょるとして(「button1」が「開始」、「button2」が「停止」)。  タイマ起動時に、下記のメソッドを呼び出すとしますわな。

public void startTimer()
{
	if (timer != null)
	{
		if (timer.Enabled)
		{
			return;
		}
	}

	timer = new System.Timers.Timer(タイムアウト時間);
	timer.Elapsed += button2_Click;
	timer.AutoReset = false;       // 1回だけ実行
	timer.Start();
}
 すると、タイムアウト時に。  「button2_Click」の「button1.Enabled = true;」の行で。

System.InvalidOperationException: '有効ではないスレッド間の操作: コントロールが作成されたスレッド以外のスレッドからコントロール 'button1' がアクセスされました。'
 という例外が発生するのです。  これを解決するのが、「Control.Invoke()」メソッドです。  下記のような説明書きになっています。
コントロールの基になるウィンドウ ハンドルを所有するスレッドでデリゲートを実行します。
 このデリゲートというのが、わたしには、まだ腑に落ちないのではありますが。

3. Invoke()

 下記のメソッドを書きまして。

private void buttonStop()
{
	if (timer != null)
	{
		timer.Dispose();
		timer = null;
	}

	button1.Enabled = true;
	button2.Enabled = false;
}
 前出「button2_Click()」メソッドを下記のように変更します。

private void button2_Click(object? sender, EventArgs e)
{
	Invoke(new Action(buttonStop));
}
 これで、丸くおさまりますじゃ。
AbemaTV 無料体験
ベルリッツ