Visual Studio 2005 C#.netです。
クラスからフォームをバックグラウンドスレッド起動して、そのフォームを起動したクラスから正常にフォームを消去させたい(終了)させたいのですが、どうすればいいのでしょうか?
現在、以下のプログラムにて実現していますが、Abortで強制終了させているのでDispose();
も行われていないと思います。
呼び出し側からアクションを起こしてAbortではなく、スレッド側から正常に終了させたいのです。
また、Showメソッドだとフォーム表示が一瞬で終わってしまうのは何故でしょうか?
よろしくお願いいたします。
クラス:
public class FormDisplayClass
{
//スレッド
private System.Threading.Thread thread;
//フォーム
private TestForm TF = new TestForm();//フォームは別に存在するとします。
//表示メソッド
public void Show()
{
//スレッド設定
this.thread = new System.Threading.Thread(
new System.Threading.ThreadStart(FormShow));
//バックグラウンド
this.thread.IsBackground = true;
//スタート
this.thread.Start();
}
/// <summary>
/// スレッドを終了させる。
/// </summary>
public void Close()
{
this.thread.Abort();
}
/// <summary>
/// フォームを表示させる
/// </summary>
private void FormShow()
{
this.SWD.ShowDialog();//表示
(Showだと表示を持続できない)
this.SWD.Dispose();
}
#endregion
}
呼び出し側:
FormDisplayClass FDC = new FormDisplayClass();
private 表示メソッド
{
FDC.Show();
}
private 終了メソッド
{
sw.Close();
}
}
よろしくお願いします。
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が終了する
}
といった具合でしょう ・・・
早速のアドバイスありがとうございます。
うまく行きました。
ありがとうございました。
このフラグ&ループのリソース使用については、
負担がかからないものなのでしょうか。
No.6
- 回答日時:
> DoEventsをWhileでループさせる場合、Sleepを入れないとビジー状態になるという件ですが、
> そのままにしておくとどのような弊害が起こるのでしょうか?
少々勘違いがあるようです
Sleepを入れる、入れないではなくて DoEventsを入れるかどうかなのです
DoEventsを入れずにwhileループをまわしても TestForm側のイベント処理等が何もされなくなってしまうという現象が起きます
これはスレッドが実行すべき項目が whileループの中だけにとどまってしまうためです
SleepやWaitOneなどで他の処理へCPUの力を振り分ける機会を多くしてやればいいかと思いますよ
解説有難うございます。
少しずつ理解出来てきたと思います。
とりあえずは、フラグ&ループの形式で目的は達しているので、
これで行きたいと思います。
色々ご親切にありがとうございました。
また、何かの時はよろしくお願いいたします。
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();
}
}
といった具合です ・・・
アドバイス有難うございます。
AutoResetEventsを試してみたところ、
動作はしましたが、ご指摘の通り、動作が遅い状況となりました。
一つ教えて頂きたいのですが、
DoEventsをWhileでループさせる場合、
Sleepを入れないとビジー状態になるという件ですが、
そのままにしておくとどのような弊害が起こるのでしょうか?
また、5mmSec程度のsleepをループに噛ます事でこの弊害を
回避する事が出来ていると言えるのでしょうか?
大変恐縮ですが、よろしくお願いいたします。
No.4
- 回答日時:
スプラッシュウィンドウを表示させたいのであれば
そのアプリのメインフォームのコンストラクタでスプラッシュウィンドウ用のフォームをインスタンス化してShowしてしまえばいいように思います ・・・
で、メインフォームのShownイベントでそのスプラッシュをCloseすればいいのでは ・・・
と感じますがいかがなのでしょう
カクカクした動きになるのは Sleepの具合だと思いますので 500を小さくしてみましょう
または Thread.Sleepで待つのではなくてAutoResetEventのWaitOneとかで待つようにするとかでしょうか
メインフォーム側のループの中に 100毎とか500毎などに
Application.DoEvents() を実行してみるとか ・・・
お返事が遅くなって申し訳ありません。
AutoResetEventについて調べいるのですが、
どこにどう挿入すれば良いのかを理解するのにはもう少し時間がかかりそうです。
とりあえず、Sleepの値を小さくしてなんとか目的は果たせそうですので、
これで凌いでいこうと思います。
有難うございました。
No.3
- 回答日時:
何をどのようにしたいのかの情報がわれわれ回答者にはまったくありません
スレッド仕立てにしてFormを管理ってのはあんまりしないと思います
逆に Formの中にスレッドをこしらえて このスレッドから来るイベントやメッセージによりFormの描画を変更する
といったことはよくやる手ですよ
2005以降なら BackgroundWorkerなどがありますし ・・・
この回答への補足
アドバイス有難うございます。
情報が欠落していました。失礼しました。
目的の動作ですが、
起動に時間のかかる同C#アプリケーションがあり、そのアプリケーションが起動するまでの間(shownイベントまで)
「起動中です」という、例えばウインドウズが起動中に出すような動きのある画面を出しておきたいのです。
ただ、この機能は他にも転用可能としてクラス化し、当然、呼び出す側はインスタンス、
show,close等の簡単な記述で完了させたいと言う事が目的です。
今回は、この表示(form)をクラスからThreadで起動し、表示をしようと考えておりました。
目的を記述するのはマナー違反かと思い自粛していた次第です。
何か、アドバイスありましたらよろしくお願いいたします。
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を挿入してみてください
アドバイスありがとうございます。
sleepを挿入してみたのですが、
表示しているフォーム上に、
オブジェクトを動かす動作をしているのですが、
これがsleepの影響を受けてうまく動きません。
そもそも、Thread上でフォームの表示を行うのは
イレギュラーなのでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- C言語・C++・C# C# DatagridviewにExcelシートを反映するとエラーが出る 2 2023/05/06 17:12
- Visual Basic(VBA) ユーザーフォーム「frm_基本❶」を立ち上げると新規で入力する行数を右下のNoとして表示しています。 1 2023/03/16 19:02
- C言語・C++・C# TCP/IP通信時のサーバーからの受信 2 2022/11/23 09:11
- Access(アクセス) Vba Userformを前面に出すについて 3 2022/04/15 12:29
- JavaScript 入力フォームの javascript で メールアドレスの正規チェックをを行い、ボタンをクリックして 2 2022/04/27 16:06
- PHP ここでの ②if($su_d<>"")の比較演算子 を使う理由は 1 2022/03/26 02:33
- JavaScript フォームが空欄の時にフォームの外をクリックすると、エラーが出るコードを調べています。 1 2023/06/25 11:51
- Visual Basic(VBA) フレームワーク「4.8.1」で、[Sub Main]が動かない。助けて下さい 3 2022/11/14 15:40
- Access(アクセス) Accessでセレクタをダブルクリックで別フォームで詳細表示 3 2022/12/20 10:36
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
どなたかこのプログラミングを...
-
VBA for i=1 to lastrow
-
画面を強制的に再描画させる方法
-
vb.netからエクセル関数書き込み
-
vb.netです。2次元配列の要素を...
-
プログラミングについて。 1つ...
-
DoEventsが必要な理由について
-
流れ図(フローチャート)が分か...
-
VBAでの一時停止と再開の方法
-
Escキーを押すと、中断する時と...
-
範囲指定したセルを1つずつ飛...
-
GIFアニメをループさせたくない
-
ループ内での条件処理
-
vbscriptでIE自動入力(途中で...
-
javaのループ処理の結果を足し...
-
スレッド起動したフォームを正...
-
VB2010でCSVファイルの読み込み
-
UWSCの終了の仕方
-
イベントの発生を待つ
-
DOSコマンドのループ内のTIMEコ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
画面を強制的に再描画させる方法
-
VBAで3秒だけ時間を止めたい
-
VBAでの一時停止と再開の方法
-
どなたかこのプログラミングを...
-
Escキーを押すと、中断する時と...
-
UWSCの終了の仕方
-
エクセルの当番表を作っていま...
-
VBA for i=1 to lastrow
-
「偶数・奇数の和」のフローチ...
-
アクティブセルから、A列最終行...
-
DoEventsが必要な理由について
-
vb.netからエクセル関数書き込み
-
GIFアニメをループさせたくない
-
DOSコマンドのループ内のTIMEコ...
-
範囲指定したセルを1つずつ飛...
-
流れ図(フローチャート)が分か...
-
乱数の桁数指定、または範囲指定。
-
テキストボックスの名前に変数...
-
CSVファイルの特定の行だけを読...
-
vbscriptでIE自動入力(途中で...
おすすめ情報