処理内でのtextBox更新 – プログラミング – Home

通知
すべてクリア

[解決済] 処理内でのtextBox更新


michu
 michu
(@michu)
ゲスト
結合: 14年前
投稿: 2
Topic starter  

色々と検索してみたのですがどうにも分からず、質問させて頂きます。

ボタンイベントの関数の中で、シリアルポートのオープン(相手とのコネクション含む)な
どの数十秒の時間の掛かる処理を呼んでいます。

で、この進捗具合をtextBoxに表示していきたいのですが、
textBox->textに値を入れても、ボタンイベント関数そのものを抜けるまでtextBoxの表示
が更新されません。

強制的にこれを再描画させる方法は無いでしょうか?
それともやはり 処理を分割していちいち抜ける(タイマー等でシーケンスを作って順次関
数を抜ける)ことになるんでしょうか。


引用未解決
トピックタグ
maru
 maru
(@maru)
ゲスト
結合: 17年前
投稿: 358
 

何かの長い処理の途中でユーザインターフェース(UI)を変更するには、通常スレッド
を使用します。マルチスレッド、ワーカスレッド、UIスレッドで検索すれは、いろいろ
例が出てくるでしょう。


返信引用
らっきょ
 らっきょ
(@らっきょ)
ゲスト
結合: 14年前
投稿: 1
 

再描画メッセージ(WM_PAINT)を処理するタイミングがないので、表示を更新でき
ないものと思われます。

文字通り強制的に再描画なら、textBox(EditBox?)に対してUpdateWindow()を行
うことです。でも、あまりお勧めではありません。
別のウィンドウが再描画されなくて困るかも知れないからです。

お勧めは時間の掛かる処理をスレッド化することにより、時間の掛かる処理と
無関係に再描画できるようにすることです。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

まず、Windowsのお約束としてメッセージハンドラは
極力短い時間で処理を終了し、メッセージループに
制御を返す必要があると言うのがあります。

大昔は3秒とか言ってましたが、
最近では0.1秒で処理を終了して関数を終了する
と言うのがルールになっています。

ですからイベントで呼び出される関数内で
長い時間が掛かる重い処理とか
接続待ち等の待ちが入る処理を行うのはルール違反になります。
これをやってしまうとアプリのタイトルバーに(応答なし)と表示されます。

皆さんが言われているように通常はウインドウの制御をメインスレッドで
行なって、直接ウインドウの制御が必要ない処理はワーカースレッドにして
マルチスレッドで動作させるのが今の流れですね。

御本人が言われているように処理をこま切れにして
タイマーを使って自前で制御する手も有りますが、
処理途中の情報とか諸々を適切に管理する必要があるので
結構めんどくさいです。

ワーカースレッドを併用する方法は基本的なやり方や仕組みを
理解してしまえば、そこまで難しい事は無いと思うので
チャレンジしてみる事をお勧めします。

マルチコアのCPUが当たり前に手に入る時代になりましたし、
マルチスレッドを使ったプログラミングの知識も特別な物では
なくなってきていると思います。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

ちなみにですが、基本的な流れとして画面の描画は
一旦、メッセージループに制御が戻った時に行われます。
これは、OSからWM_PAINTのメッセージが来たタイミングで
画面の再描画を行なう仕組みになっているからです。

画面の描画は、それ以外の計算やデータの処理の合間に
行なうような形になっていますから、そういった処理が
長い時間制御を占有してしまうと再描画ができなくなって
しまうわけです。

強制的に再描画を行う事も可能ですが、
描画処理は結構重い処理なので自分の都合だけで
行なってしまうと他のウインドウに支障が出たりします。
Windowsは複数のアプリが同時に起動した状態になりますから
自分アプリの都合だけで処理を行うと他のアプリに迷惑が
掛かってしまいます。
ですから、基本的なWindowsのルールに従った作りにしておく必要があります。

この辺は、Windowsプログラミングの解説書等で勉強される事をお勧めします。


返信引用
瀬戸っぷ
 瀬戸っぷ
(@瀬戸っぷ)
ゲスト
結合: 14年前
投稿: 5
 

こういった必要性から、ワーカースレッドで処理するように切り替えた場合に
お約束的に問題になる点もありますのでご注意を。

・ワーカースレッドの終了のタイミングがメインスレッド(UIスレッド)側で判らない
=>ワーカースレッドから、メインスレッドにメッセージを投げることで通知しましょう。

・ワーカースレッドが多重に起動する
=>ボタン押下などの契機でワーカースレッドを起動する場合、多重起動が望ましくない場
合は排他制御しましょう。(ボタンに対してEnableWindow()等で無効化するのが一般的)

・走り出したワーカースレッドを任意に止めたい(中断したい)
=>イベントオブジェクトなどで通知してワーカースレッドが自分で終了できるような作り
にしましょう。(TerminateThread()で殺すのは危険ですので注意)

慣れるまではいろいろなところで躓くかもしれませんが、習得しておくと便利です。


返信引用
michu
 michu
(@michu)
ゲスト
結合: 14年前
投稿: 2
Topic starter  

みなさまレス頂いてありがとうございます。

今回作っているソフトは私的な物ですが、
組込系出身のため(ベタなアセンブラ・C)なかなかに苦労しております。
なんというか、勝手が違いすぎて簡単(なハズ)な事で躓きまくって凹むことしきりです。
どういうキーワードで調べれば良いか?の勘がつくくらいまではタイヘンそうです。

ワーカスレッドのほうはこれから調べて試行してみます。

ワーカスレッドのほうはちょっと時間かかりそうなので、
さしあたってはtextBox->Update()で逐次(強制)更新できるようにできました。

ありがとうございました。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました