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

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

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

Re[2]: VB.netでBG処理結果をタブへ表示したい


(過去ログ 139 を表示中)

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

■81643 / inTopicNo.1)  VB.netでBG処理結果をタブへ表示したい
  
□投稿者/ わかば (1回)-(2016/10/21(Fri) 17:53:43)

分類:[.NET 全般] 

大変おせわになります。

VB.netで作成したフォームにタブコントロールを貼りつけまして
BackGroundWorkerとCallback機能を使って
PCの通信ポートから受信したデータ(数値)を
タブ上のテキストボックスやビットマップ(グラフ)へ即時に表示したいと思います。
タブ上のコントロールは、できれば動的に作成したいです。

上記のようなことはできるのでしょうか?
自分でもタブとBackGroundWorkerの組み合わせを試行錯誤したり調べるのですが失敗しています。
それにデバッグモードが使えなくて困っております....
環境はVS Express 2013 for Desktopです。

かなりざっくりとした説明で恐縮ですが、できるorできない でも結構ですので
知見のある方、ご回答いただけましたら幸いです。

引用返信 編集キー/
■81649 / inTopicNo.2)  Re[1]: VB.netでBG処理結果をタブへ表示したい
□投稿者/ Azulean (729回)-(2016/10/21(Fri) 22:43:17)
No81643 (わかば さん) に返信
> BackGroundWorkerとCallback機能を使って
> PCの通信ポートから受信したデータ(数値)を
> タブ上のテキストボックスやビットマップ(グラフ)へ即時に表示したいと思います。
> タブ上のコントロールは、できれば動的に作成したいです。
>
> 上記のようなことはできるのでしょうか?

基本的にコントロールの生成・操作は UI スレッド(メインスレッド)で実行しなければならないので、BackgroundWorker の DoWork イベントやそこから呼び出される処理では作れません。
Invoke や BeginInvoke などによって UI スレッドに処理をお願いしなければなりません。

ただ、すべての処理を UI スレッドに任せると BackgroundWorker を使う意味がなくなります。
よって、どこまでをバックグラウンドで、どこからを UI スレッドで実行するべきか、きちんと切り分ける必要があります。
また、処理のスレッドが分かれるため、同時並行させる場合は、どちらが先に実行されるか、前の UI スレッドの処理は終わっているかなど、排他・同期について考える必要があります。


ゆえに「技術的には実現できるが、スレッドに関する理解・経験がある程度求められる」という感じでしょうか。
引用返信 編集キー/
■81652 / inTopicNo.3)  Re[1]: VB.netでBG処理結果をタブへ表示したい
□投稿者/ shu (928回)-(2016/10/24(Mon) 09:06:22)
No81643 (わかば さん) に返信

CanRaiseEventsをTrue (デザイン時に設定しておけばよい)

ReportProgressメソッドを適宜実行

ProgressChangedイベントにてUI処理を実行

とすれば可能です。
ただしProgressChangedイベントの処理の完了を待たずに
BackGroundWorker.DoWorkの処理は継続されますので、
必要に応じ同期をしたり、DoWorkでの書込みとUI表示で
の読み込みが衝突しないよう工夫する必要はあるかと思います。
引用返信 編集キー/
■81665 / inTopicNo.4)  Re[2]: VB.netでBG処理結果をタブへ表示したい
□投稿者/ わかば (2回)-(2016/10/25(Tue) 10:25:33)
No81649 (Azulean さん) に返信
Azuleanさん

大変おせわになります。

TabPage.Controls.Add(panel)
panel.Controls.Add(picturebox)

のように動的に作成した描画エリアへグラフを表示したかったのです。
Invokeを介して

PictureBox.Image = bmp

としても表示されなかったのですが、よく確認したところ
原因は変数名のスペルミスと判明いたしました....。;
お騒がせして大変申し訳ございませんでした。
とはいえAzuleanさんの「できる」とのコメントがなければ挫折しておりました。
本当にありがとうございます。


> 基本的にコントロールの生成・操作は UI スレッド(メインスレッド)で実行しなければならないので、BackgroundWorker の DoWork イベントやそこから呼び出される処理では作れません。
> Invoke や BeginInvoke などによって UI スレッドに処理をお願いしなければなりません。
>
> ただ、すべての処理を UI スレッドに任せると BackgroundWorker を使う意味がなくなります。
> よって、どこまでをバックグラウンドで、どこからを UI スレッドで実行するべきか、きちんと切り分ける必要があります。

できるだけUI処理のコードのみUIスレッド内で実行するようにとのことですね。
BackgroundWorkerの中でInvokeを使ってUIスレッドを実行しようとしていますが、
便利だからといって余分なコードを詰め込んだりしないように、気を付けます。


> また、処理のスレッドが分かれるため、同時並行させる場合は、どちらが先に実行されるか、前の UI スレッドの処理は終わっているかなど、排他・同期について考える必要があります。

BackgroundWorkerの中でAsyncCallbackを使ってデータ受信をしています。
Callback関数の中で電文からデータ取り出しが終了したら
pictureboxへグラフ(ビットマップ)表示とlistboxへデータ表示をします。
電文処理の途中で表示とかしないようにフラグとRWlockを使っているのですが、
そういえば受信が停止してしまうことがあるので、排他がきちんとできていないかもしれないです。
同期の方法についても勉強しようと思います。

有難うございました。
引用返信 編集キー/
■81670 / inTopicNo.5)  Re[2]: VB.netでBG処理結果をタブへ表示したい
□投稿者/ わかば (3回)-(2016/10/25(Tue) 18:58:40)
No81652 (shu さん) に返信

shuさん

ご回答有難うございます。

> CanRaiseEventsをTrue (デザイン時に設定しておけばよい)

リファレンス調べてみました。
何となく理解できる気がしますが呼び出し方が判らず;でした。
いつか使いこなせると良いのですが。

> ReportProgressメソッドを適宜実行
>
> ProgressChangedイベントにてUI処理を実行
>
> とすれば可能です。
> ただしProgressChangedイベントの処理の完了を待たずに
> BackGroundWorker.DoWorkの処理は継続されますので、
> 必要に応じ同期をしたり、DoWorkでの書込みとUI表示で
> の読み込みが衝突しないよう工夫する必要はあるかと思います。

確かに、ProgressChangedイベントの中でグラフ表示など実行すればできそうですね!
今作成しているプログラムのように、UI処理(グラフ表示とデータ表示)を同時のタイミングで行う場合
Invokeを使うよりこの方法のほうが適していると思いました。
ちなみにデータは受け渡しはバッファを使用ですね。

有難うございました。
引用返信 編集キー/
■81671 / inTopicNo.6)  Re[1]: VB.netでBG処理結果をタブへ表示したい
□投稿者/ わかば (4回)-(2016/10/25(Tue) 19:00:30)
おかげさまで解決済みです。
解決済み
引用返信 編集キー/
■81675 / inTopicNo.7)  Re[3]: VB.netでBG処理結果をタブへ表示したい
□投稿者/ shu (930回)-(2016/10/26(Wed) 10:29:19)
No81670 (わかば さん) に返信
>
>>CanRaiseEventsをTrue (デザイン時に設定しておけばよい)
>
> リファレンス調べてみました。
> 何となく理解できる気がしますが呼び出し方が判らず;でした。
> いつか使いこなせると良いのですが。

WorkerReportsProgressの間違いでしたmm


解決済み
引用返信 編集キー/
■81677 / inTopicNo.8)  Re[2]: VB.netでBG処理結果をタブへ表示したい
□投稿者/ なちゃ (146回)-(2016/10/26(Wed) 21:47:37)
No81671 (わかば さん) に返信
> おかげさまで解決済みです。

今更ですが、UI側に渡すデータは、ReportProgressの引数のuserState辺りで、新しく作成したオブジェクト、つまりワーカー側処理では以降一切さわらないオブジェクトを渡すようにしましょう。
例えば配列データを渡す必要があるなら、ワーカー側では二度とさわらない配列を作成して、そこにデータを詰めて渡します。
このようにすることで、双方でのデータ共有が発生せず、競合を避けられるようになります。
競合しても問題ないようにロックなどを掛けるのではなく、最初からそもそも共有しないようにデータを渡すのが重要です。
解決済み
引用返信 編集キー/


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

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -