• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:スレッド起動したフォームを正常に終了させる。)

スレッド起動したフォームを正常に終了させる方法

このQ&Aのポイント
  • Visual Studio 2005 C#.netを使用して、クラスからフォームをバックグラウンドスレッドで起動し、正常に終了させる方法について教えてください。
  • 現在、スレッドをAbortで強制終了させているため、Dispose()が正しく行われていない問題があります。呼び出し側からアクションを起こし、スレッド側からフォームを正常に終了させる方法を知りたいです。
  • また、Showメソッドを使用するとフォームの表示が一瞬で終わってしまう問題があります。この理由も教えてください。

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

FormDisplayClassにスレッドの実行関数を用意します またフォームが開いているかどうかを表すフラグも用意します // フォームを閉じるためのフラグ private Bool bFlag; // スレッド実行関数 protected void myProc() {   // フォームを表示   this.TF.Show();   // フォームが破棄されるまでループを回る   while ( !this.TF.IsDisposed )   {     // 他のスレッド止めないための処理     Application.DoEvents();     // 破棄される前に 閉じろフラグが立った時     if ( bFlag && !this.TF.IsDisposed )     {       this.TF.Close();     }   } } public void show() {   // フォームが破棄されている場合   if ( !this.TF.IsDisposed )   {     this.TF = new TestForm();   }   bFlag= false;   //スレッド設定   this.thread = new System.Threading.Thread( new System.Threading.ThreadStart(myProc));   //バックグラウンド   this.thread.IsBackground = true;   //スタート   this.thread.Start(); } public void Close() {   // フラグをセットするだけにする   bFlag = true;   // 次回のmyProc内のループでフラグがチェックされてフォームが閉じる   // フォームが閉じるとwhileループを抜け myProcも終了   // この時点でthreadが終了する } といった具合でしょう ・・・

cinquecent
質問者

お礼

早速のアドバイスありがとうございます。 うまく行きました。 ありがとうございました。 このフラグ&ループのリソース使用については、 負担がかからないものなのでしょうか。

すると、全ての回答が全文表示されます。

その他の回答 (5)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.6

> DoEventsをWhileでループさせる場合、Sleepを入れないとビジー状態になるという件ですが、 > そのままにしておくとどのような弊害が起こるのでしょうか? 少々勘違いがあるようです Sleepを入れる、入れないではなくて DoEventsを入れるかどうかなのです DoEventsを入れずにwhileループをまわしても TestForm側のイベント処理等が何もされなくなってしまうという現象が起きます これはスレッドが実行すべき項目が whileループの中だけにとどまってしまうためです SleepやWaitOneなどで他の処理へCPUの力を振り分ける機会を多くしてやればいいかと思いますよ

cinquecent
質問者

お礼

解説有難うございます。 少しずつ理解出来てきたと思います。 とりあえずは、フラグ&ループの形式で目的は達しているので、 これで行きたいと思います。 色々ご親切にありがとうございました。 また、何かの時はよろしくお願いいたします。

すると、全ての回答が全文表示されます。
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.5

メインスレッド側で何かのプロシージャやイベントの中で ビジーループ(大きなループ処理でメッセージポンプを止めてしまうようなもの)があるとカクカクした動きはSleepを小さくしても直らないかもしれません AutoResetEventについては クラスのメンバーとして宣言しておいて スレッドのメインループの中でSleepを使用している部分と置き換えます class FomDisp { private AutoResetEvent myEvent; private Thread thread; private TestForm TF; // コンストラクタ Public FormDisp() { thread = new Thread( new ThreadStart( myProc ) ); myEvent = new AutoResetEvent( false ); } // スレッドのメインループ private void myProc() {   TF.Show();   // イベントがセットされるまで 100ms待機する   while ( !myEvent.WaitOne( 100, false ) ) {     Application.DoEvents();   }   TF.Close(); } public void show() {   TF = new TestForm();   thread.Start(); } publicvoid close() {   // メインループを終了するためにセットする   myEvent.Set(); } } といった具合です ・・・

cinquecent
質問者

お礼

アドバイス有難うございます。 AutoResetEventsを試してみたところ、 動作はしましたが、ご指摘の通り、動作が遅い状況となりました。 一つ教えて頂きたいのですが、 DoEventsをWhileでループさせる場合、 Sleepを入れないとビジー状態になるという件ですが、 そのままにしておくとどのような弊害が起こるのでしょうか? また、5mmSec程度のsleepをループに噛ます事でこの弊害を 回避する事が出来ていると言えるのでしょうか? 大変恐縮ですが、よろしくお願いいたします。

すると、全ての回答が全文表示されます。
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

スプラッシュウィンドウを表示させたいのであれば そのアプリのメインフォームのコンストラクタでスプラッシュウィンドウ用のフォームをインスタンス化してShowしてしまえばいいように思います ・・・ で、メインフォームのShownイベントでそのスプラッシュをCloseすればいいのでは ・・・ と感じますがいかがなのでしょう カクカクした動きになるのは Sleepの具合だと思いますので 500を小さくしてみましょう または Thread.Sleepで待つのではなくてAutoResetEventのWaitOneとかで待つようにするとかでしょうか メインフォーム側のループの中に 100毎とか500毎などに Application.DoEvents() を実行してみるとか ・・・

cinquecent
質問者

お礼

お返事が遅くなって申し訳ありません。 AutoResetEventについて調べいるのですが、 どこにどう挿入すれば良いのかを理解するのにはもう少し時間がかかりそうです。 とりあえず、Sleepの値を小さくしてなんとか目的は果たせそうですので、 これで凌いでいこうと思います。 有難うございました。

すると、全ての回答が全文表示されます。
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

何をどのようにしたいのかの情報がわれわれ回答者にはまったくありません スレッド仕立てにしてFormを管理ってのはあんまりしないと思います 逆に Formの中にスレッドをこしらえて このスレッドから来るイベントやメッセージによりFormの描画を変更する といったことはよくやる手ですよ 2005以降なら BackgroundWorkerなどがありますし ・・・

cinquecent
質問者

補足

アドバイス有難うございます。 情報が欠落していました。失礼しました。 目的の動作ですが、 起動に時間のかかる同C#アプリケーションがあり、そのアプリケーションが起動するまでの間(shownイベントまで) 「起動中です」という、例えばウインドウズが起動中に出すような動きのある画面を出しておきたいのです。 ただ、この機能は他にも転用可能としてクラス化し、当然、呼び出す側はインスタンス、 show,close等の簡単な記述で完了させたいと言う事が目的です。 今回は、この表示(form)をクラスからThreadで起動し、表示をしようと考えておりました。 目的を記述するのはマナー違反かと思い自粛していた次第です。 何か、アドバイスありましたらよろしくお願いいたします。

すると、全ての回答が全文表示されます。
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

スレッド実行ループがビジーループに近い状態ですのでちょっとまずいですね protected void myProc() {   // フォームを表示   this.TF.Show();   // フォームが破棄されるまでループを回る   while ( !this.TF.IsDisposed )   {     // 他のスレッド止めないための処理     Application.DoEvents();     // 破棄される前に 閉じろフラグが立った時     if ( bFlag && !this.TF.IsDisposed )     {       this.TF.Close();     }     // ここに追加     Thread.Sleep( 500 );   } } といった感じで Sleepを挿入してみてください

cinquecent
質問者

お礼

アドバイスありがとうございます。 sleepを挿入してみたのですが、 表示しているフォーム上に、 オブジェクトを動かす動作をしているのですが、 これがsleepの影響を受けてうまく動きません。 そもそも、Thread上でフォームの表示を行うのは イレギュラーなのでしょうか?

すると、全ての回答が全文表示されます。

関連するQ&A