C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Invokeの使い方に関して

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■96477 / inTopicNo.1)  Invokeの使い方に関して
  
□投稿者/ 心身 (1回)-(2020/11/27(Fri) 22:48:48)

分類:[.NET 全般] 

VB.NETに関する質問です。

バックグラウンドスレッドからGUI上のコントロールを操作する場合
BeginInvokeあるいはInvokeを使う必要があります。


これらを使う時、
バックグラウンドスレッドのコードがForm Class上にあれば
そのままでいけますが、別のモジュールやクラスにある場合、
予め
Public fff1 = Form1
のようにフォームの変数をセットしておいて、

バックグラウンドスレッドにおいて、
fff1.BeginInvokeあるいはfff1.Invoke
のようにして呼び出す必要があります。

ここで疑問は、
複数フォームがある場合には、
fff1の部分は操作したいコントロールがあるフォームにする必要はあるのでしょうか?


実際試してみると、該当するコントロールのないフォームであっても
コントロールを操作することができますが、
フォーム名とコントロールを合わせる必要があるのでしょうか?

何となく、同じフォームに何度もInvokeすると行列ができてしまうため、
別のフォームに投げた方が良いのではないかと思うのですが
そんなことはあるのでしょうか?



引用返信 編集キー/
■96478 / inTopicNo.2)  Re[1]: Invokeの使い方に関して
□投稿者/ Hongliang (1128回)-(2020/11/27(Fri) 23:22:45)
> ここで疑問は、
> 複数フォームがある場合には、
> fff1の部分は操作したいコントロールがあるフォームにする必要はあるのでしょうか?
>
> 実際試してみると、該当するコントロールのないフォームであっても
> コントロールを操作することができますが、
> フォーム名とコントロールを合わせる必要があるのでしょうか?

特にないです。
操作する対象のコントロールが生成されたのと同じスレッドで生成されたフォームやコントロール(一般的にはすべてそうです)であればどれでも構いません。
しかし、そもそも操作するコントロールはそこにあるのでしたら、それのInvoke/BeginInvokeを使うのが手っ取り早いし確実なのではないでしょうか?

> 何となく、同じフォームに何度もInvokeすると行列ができてしまうため、
> 別のフォームに投げた方が良いのではないかと思うのですが
> そんなことはあるのでしょうか?

何の影響もありません。
そもそもInvokeは同期実行なので行列も何もありません。
BeginInvokeも投げられた処理はコントロールやフォーム単位で管理されるではなく、それらが生成されたスレッドが順次処理するものです。
引用返信 編集キー/
■96479 / inTopicNo.3)  Re[2]: Invokeの使い方に関して
□投稿者/ 心身 (2回)-(2020/11/28(Sat) 10:02:18)
No96478 (Hongliang さん) に返信

ありがとうございます。

バックグラウンドスレッドは複数走らすことができるのに対し
GUIスレッドはフォームを複数もっていたとしても、一つしか走らすことができません。

そのため、Begininvokeやinvokeの頭にフォームクラスを引数として受け取る意味がないように思います。
フォームクラスを引数として受け取るからには、
フォームごとに使い分けるケースがあるのではないかと思いましたが
そういうわけではないということで合っていますか?
 
引用返信 編集キー/
■96480 / inTopicNo.4)  Re[3]: Invokeの使い方に関して
□投稿者/ 魔界の仮面弁士 (2929回)-(2020/11/28(Sat) 11:04:47)
2020/11/28(Sat) 11:27:09 編集(投稿者)

No96479 (心身 さん) に返信
> バックグラウンドスレッドは複数走らすことができるのに対し
> GUIスレッドはフォームを複数もっていたとしても、一つしか走らすことができません。

認識としてはそれでよいと思います。
それぞれの UI スレッドは独立しており、スレッドを跨いだ操作は既定で禁止されています。

ただし、アプリ内のメッセージループは一つだけとは限りません。
スプラッシュスクリーンだとか、非同期通信モジュールの通知ダイアログのように、
一つのアプリ内で複数の UI スレッドが存在することもあります。

 void button1_Click(object sender, EventArgs e) {
   button1.Text = "変えてやる!"; // こっちは成功する
   anotherFormButton.Text = "変えてみたい"; // こっちはどうだろう?
 }

anotherFormButton が、自フォームから呼び出したフォーム上のボタンならば
何の問題もありません。button1 と同様に書き換えられます。

しかし button1 と anotherFormButton が異なる UI スレッドに所属していた場合、
既定の設定では、anotherFormButton への操作が InvalidOperationException で停止します。

このような場合は、InvokeRequired で問い合わせて判断します。

 void button1_Click(object sender, EventArgs e) {
   button1.Text = "変えてやる!"; // こっちは成功する
   if (anotherFormButton.InvokeRequired) {
     // 別スレッドだったので、相手先のスレッドに作業を依頼
     anotherFormButton.Invoke(new MethodInvoker(() => anotherFormButton.Text = "変えてみたい"));
   } else {
     // 同一スレッドなので、自分で作業できる
     anotherFormButton.Text = "変えてみたい";
   }
 }


この時、『anotherFormButton.InvokeRequired』のプロパティ呼び出しを
「InvokeRequired」「this.InvokeRequired」「button1.InvokeRequired」などと書いてはいけません。
(Invoke や BeginInvoke も同様です)


一方、this と button1 が同一の UI スレッドであるため、
this.InvokeRequired と button1.InvokeRequired は同一の意味を持ちます。

 if (this.InvokeRequired) {
   // this.InvokeRequired も button1.InvokeRequired も false になる
   Invoke(new MethodInvoker(() => button1.Text = "変えてみせる"));
 } else {
   // 常にこっちが呼び出される
   button1.Text = "変えてみせる";
 }

もちろん、button1_Click 内で button1 を操作する場合には、
そもそも InvokeRequired 判定自体が不要です。


> Begininvokeやinvoke
BeginInvoke や Invoke 、ですね。


> の頭にフォームクラスを引数として受け取る意味がないように思います。
(Begin)Invoke は、Form クラスに実装されたメンバーではなく、
その親クラスである Control クラスにて実装されています。

Form であれ Button であれ Label であれ、どの Control の Invoke を呼び出したとしても、
同じ UI スレッドに所属するコントロールである場合には、振る舞いは同一です。
引用返信 編集キー/
■96481 / inTopicNo.5)  Re[3]: Invokeの使い方に関して
□投稿者/ Hongliang (1129回)-(2020/11/28(Sat) 11:13:33)
最初の投稿からも少し勘違いされてるように見受けられたのですが、Invoke/BeginInvokeを持っているのはFormクラスではなくてその基底クラスであるControlクラスです。
ですので、フォームごとにと言うのは前提自体が存在していません。
TextBox1.Invoke(...)でも問題ないので。
引用返信 編集キー/
■96517 / inTopicNo.6)  Re[4]: Invokeの使い方に関して
□投稿者/ 心身 (3回)-(2020/12/06(Sun) 12:03:20)
>スプラッシュスクリーンだとか、非同期通信モジュールの通知ダイアログのように、
一つのアプリ内で複数の UI スレッドが存在することもあります。

UIスレッドでもマルチスレッドできる場合があるのですね
どうもありがとうございました。

解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ