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

「開始」と同時に、タイマを起動して、「停止」ボタンが押されるか、タイマがタイムアウトしたら、停止するということで。
「停止」ボタン押下時のイベント処理が。
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));
}
これで、丸くおさまりますじゃ。
|
|