- - PR -
別スレッドで開いたフォームの破棄について
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2006-08-17 15:14
アプリの構成が以下のようになっています。
---------------------------------------- Mainフォーム(Form) ↓ 処理管理クラス ↓ ↓ プログレス画面 処理別フォーム (Form) (Form) ---------------------------------------- 処理管理クラスでは、別スレッドでShowDialog()を用いてプログレス画面を呼び出しています。 スレッドは、以下のように扱っています。 ・thread.Start(); ・thread.Abort(); で、thread.Abort()でプログレス画面を破棄し、処理別フォームを表示させた際、プログレス画面が画面上に残ってしまいます。 (メインフォームや、処理別フォームをクリックすればプログレス画面は消えます。) 描画が問題だと思ったので、処理別フォームを表示する際に、Reflesh()をやってみたのですが、プログレス画面は画面上に残ったままでした。 どのようにすれば、別スレッドのダイアログを画面上から消すことができるのでしょうか? わかる方いたら、教えてくださいm(__)m | ||||
|
投稿日時: 2006-08-17 16:28
Threadを終了することとフォームを破棄することはまったくの別問題です。 Threadはウィンドウではないので、つまり描画するものが無いというか描画という概念が存在しません。 その中で扱うものはその中できちんと始末してあげる必要があります。 他のきっかけで消えるのは、そのきっかけで再描画がおこなわれたときにフォームの存在(ウィンドウハンドル)が無く お掃除してくれるからです。 あと、なぜAbortなのかという問題もあります。 よほど処理続行不可能な状態だと判断したときくらいしか使わないはず。 「プログレス画面を閉じなさい」と外から要求できるインターフェースを実装して そこで処理すればよいと思います。 もひとつ。 最終目的が要求された処理別フォームを表示することが目的で、前処理が重いなど妥当な理由が無ければ 別スレッドにする必要性を想像できないのですが。 何か理由があるのでしょうか? あとGUIを別スレッドにしている理由も想像できません。 | ||||
|
投稿日時: 2006-08-17 19:57
まどかさん 回答ありがとうございます。
検索処理が重くなる場合があるため、別スレッドにてプログレス画面を表示しています。 (プログレス画面には、「キャンセル」ボタンを配置したりしています。) 検索処理が終わり、処理別フォームを表示する前にAbort()しようと考えていました。 # スレッドは初めてなので、イマイチ理解していない部分があります。。。 で、試しに以下のことをやってみました。 1.検索処理開始前にプログレス画面を別スレッドでShowDialog() 2.検索処理終了後Abort()する前に、プログレス画面をClose() ※ プログレス画面は、クラス内のPrivate変数です。 上記手順をやったところ、画面が残ってしまう現象はなくなりました。 このようなやり方ってスレッドを使う場合、普通のやり方なのでしょうか? | ||||
|
投稿日時: 2006-08-17 20:06
スレッドのAbortはどうしてもせざるを得ない場合以外はやめたほうがいいです。 そんな乱暴なことをせずとも、画面Closeでそのままスレッドが終わればいいだけではないですか? あと、個人的には、プログレス画面をメイン(というかUI側のスレッド)で、 処理の方をバックグラウンド(というか別のスレッド)で実行する方が好き。 | ||||
|
投稿日時: 2006-08-18 10:13
なちゃさん 回答ありがとうございます。
初歩的な質問になると思うのですが、今作成しているサンプルでは、下記のようにしています。 public class test { private progress pDlg; //progressは、プログレス画面クラス public void mainExe() { pDlg = new progress(); thread_Dlg = new Thread(new ThreadStart(this.showPDlg)); thread_Dlg.Start(); // 検索処理 … pDlg.Close(); thread_Dlg.Abort(); 処理別画面.ShowDialog(); … } private void showPDlg() { if (pDlg.ShowDialog() == DialogResult.Cancel) { // キャンセル処理 } } … } 上記の場合、mainExeメソッド内でpDlgをCloseすることにより、別スレッド(thread_Dlg)処理のshowPDlgメソッドが終了するので、明示的に破棄しなくてもthread_Dlgが自動的に終了するということでしょうか?? # 確かに、プログレス画面をメイン処理とした方がいいような気がしています。 # もっと、勉強が必要ですね。。。 | ||||
|
投稿日時: 2006-08-18 10:39
同感。建て増しだとしても普通そうな。 .NET 2.0 なら、それを支援する BackgroundWorker クラスなんてものもありますし。 | ||||
|
投稿日時: 2006-08-18 11:41
Threadが終了するというのはStartで指定したエントリのEnd Sub(Function)に達して抜けるということです。 Abortはあくまで「強制終了」です。 UIをメインスレッドでというのはプログレス画面をメインで表示し 入力待ちを維持しつつ別スレッドの処理から通知を受け取り表示を更新するという方法です。 下記を動かしてみるとよいかも どぼんさん−Tips−その他のTips−時間のかかる〜 http://dobon.net/vb/dotnet/index.html | ||||
|
投稿日時: 2006-08-18 12:35
渋木宏明さん、まどかさん、回答ありがとうございます。
つまり、私の書いた例の場合、「pDlg.Close(); 」を実行した時点で「thread_Dlg.Start()」が終了するので、Abort()は呼び出す必要がないってことになりますよね? 解釈の仕方が間違っているでしょうか? どちらにせよ、Abortの使い方が間違っているみたいなので、勉強しなおしますm(__)m |