DOBON.NET DOBON.NETプログラミング掲示板過去ログ

スレッドについて

環境/言語:[WindowsXP,C#,.NET Framework1.1]
分類:[.NET]

質問があります。

現在スレッドでの処理を作成しているのですが、

Thread thread = new Thread( new ThreadStart(Methoad1));
thread.Start();
thread.Join(); ←ここ

Joinの処理でFormが固まってしまいます。

Methoad1はダミーのメソッドで、
本来呼びたいメソッドをInvokeで呼び出しています。

何か回避策はありますでしょうか?
よろしくお願いします。
> Joinの処理でFormが固まってしまいます。

仕方ありません。
それが仕様ですから。

> Methoad1はダミーのメソッドで、
> 本来呼びたいメソッドをInvokeで呼び出しています。
>
> 何か回避策はありますでしょうか?

どういう結果が欲しいのかで対策は異なります。

スレッドの処理が実行されている間、Form1 をどういう状態にしておきたいのでしょうか?
また、スレッドの処理が終わったら、何をどうしたいのでしょう?
お世話になります。ラフです。

> 仕方ありません。
> それが仕様ですから。

この動きは仕様なのですね・・。

> どういう結果が欲しいのかで対策は異なります。
>
> スレッドの処理が実行されている間、Form1 をどういう状態にしておきたいのでしょうか?
> また、スレッドの処理が終わったら、何をどうしたいのでしょう?

本来やりたかった事は、
Button1を押下したイベントで処理を行うのですが、
その処理に時間がかかるため、
スレッド化し、処理が完全に終わるまで(joinで待つ)
Formの全ての動作を無効化したかったわけです。
(ただしFormのEnabled以外の制御で)

よろしくお願いします。
2005/02/28(Mon) 11:13:12 編集(投稿者)

■No9374に返信(ラフさんの記事)

こんにちは 平ちゃんです。

回答ではありません。参考にできればと思いまして。
ユーザーに処理が終わるまで「処理中なのでそっとしておいて」とメッセージをだして、マウスを画面から消すのはどうでしょうか。

処理が完了すれば「ありがとうございました。」にメッセージを変えてマウスを表示させる。

処理に入る最初の1秒位で全体の何割が処理できたかわかればそれを基に終了時刻の大体の目安を最初に表示できればなおいい。

処理中はキーボードの受付を無視出来ればいいがどうすればいいか解りませんので予めユーザーにお断りしておく。

処理が停止していない事をユーザーに知らせるため時刻を表示し、処理中は1分間隔で更新するのもいいかも知れない。

# 要は処理の短縮を図り最後はユーザーとの打ち合わせでしょうか。
# たいした内容ではありませんので参考にならなければ無視してください。


以前に似た質問がありますが同じ方でしょうか。
http://dobon.net/cgi-bin/vbbbs/cbbs.cgi?mode=al2&namber=9312&rev=&no=0
同じ方ならニックネームを統一した方が良いと思います。
2005/02/28(Mon) 12:40:35 編集(投稿者)

じゃんぬねっと です。

■No9375に返信(平ちゃんさんの記事)
> ユーザーに処理が終わるまで「処理中なのでそっとしておいて」とメッセージをだして、マウスを画面から消すのはどうでしょうか。
> 処理が完了すれば「ありがとうございました。」にメッセージを変えてマウスを表示させる。

ユーザー運用保守はよくありません。(デベロッパとして 1 番最低な仕様です)
業務では、悪意のあるユーザーを想定してください。

> 以前に似た質問がありますが同じ方でしょうか。
> http://dobon.net/cgi-bin/vbbbs/cbbs.cgi?mode=al2&namber=9312&rev=&no=0
> 同じ方ならニックネームを統一した方が良いと思います。

全然違う質問内容だと思いますが? (^-^;)



■No9361に返信(ラフさんの記事)
> Thread thread = new Thread( new ThreadStart(Methoad1));
> thread.Start();
> thread.Join(); ←ここ
> Joinの処理でFormが固まってしまいます。

Join メソッドの引数にタイムアウトを設定しましょう。
そして、ThreadState を見て終了するまで回すことで、
呼び出し元を描画するように工夫はできます。

# 「応答なしアプリケーション」防止は難しいです...
お世話になります。ラフです。

> Join メソッドの引数にタイムアウトを設定しましょう。
> そして、ThreadState を見て終了するまで回すことで、
> 呼び出し元を描画するように工夫はできます。

↑この処理についてですが・・

thread.Join(10000);
while(thread.ThreadState == ThreadState.Running)
{
Application.DoEvents();
}

こんな感じでしょうか?
これだとjoinのタイムアウトが終了してから
whileに到達するようです。。

今更なんですが、詳細な仕様です。
@グリッドの行を選択するとテキストボックスにピックアップする
A「追加ボタン」を押下するとテキストボックスに
 入力したデータをグリッドに追加する
B上記の複合でピックアップしたデータを「追加ボタン」押下によって
 コピー追加できる

問題:Bのコピー追加の際にピックアップしきる前に
   「追加ボタン」を押下されると
   空のテキストボックスのまま追加されてしまう
>Button1を押下したイベントで処理を行うのですが、
>その処理に時間がかかるため、
>スレッド化し、処理が完全に終わるまで(joinで待つ)
>Formの全ての動作を無効化したかったわけです。
>(ただしFormのEnabled以外の制御で)

要するに、回避したいのは「「時間のかかる処理」を行っている間アプリケーションがまったくの無反応になってしまうこと」なんですよね?

であれば

・新規に小さなフォームを ProgressForm 作成する。
・Button1 押下で、ProgressForm.ShoDialog() する。
・ProgressForm.Load() で「時間のかか処理」を非同期デリゲートまたはスレッドで実行開始する。
・お好みにより、「時間のかかる処理」から ProgressForm.Invoke() で進捗を報告する。
・必要なら、↑のデリゲートで、ProgressForm 上のプログレスバーなどでユーザに進捗を示す。
・「時間のかかる処理」が終了(異常終了でも)したら、ProgressForm.Invoke() で処理終了を伝える。
・↑のデリゲートで、ProgresForm.Close() する。

なんて感じにすればよろしんじゃないでしょうか。
じゃんぬねっと です。
誤解だけは解きたいので、ちょっとだけ横槍させてください。

# 残りは、ひどりさんにお任せします (^-^;)

<横槍> <!-- ごめんなさい、ひどりさん -->

■No9381に返信(ラフさんの記事)
> thread.Join(10000);
> while(thread.ThreadState == ThreadState.Running)
> {
> Application.DoEvents();
> }
> こんな感じでしょうか?
> これだとjoinのタイムアウトが終了してから
> whileに到達するようです。。

それでやるのでしたら、中ですよ、中。
while のブロック内で Join。
それと、そんな長い時間のタイムアウトじゃまずいです。
さらに言うと、while の前にスレッドが完全に Running 状態にあるかも確認すべきです。
すぐに、スレッドがスタートするとも限りませんからね。

</横槍> <!-- 横槍失礼しました -->
> それでやるのでしたら、中ですよ、中。
> while のブロック内で Join。

やるとしたらこんな感じ。

for (;;)
{
if (thread.Join (1)) break;
Application.DoEvents();
}

でもこれ、ボタンとか押せちゃうので僕的にはキライ。
  • 題名: Re[6]: スレッドについて
  • 著者: 平ちゃん
  • 日時: 2005/02/28 20:43:30
  • ID: 9396
  • この記事の返信元:
  • この記事への返信:
    • (なし)
  • ツリーを表示
■No9381に返信(ラフさんの記事)
> お世話になります。ラフです。
>

平ちゃんです。

皆様のご意見は別として質問者に疑問です。


>
> 今更なんですが、詳細な仕様です。
> @グリッドの行を選択するとテキストボックスにピックアップする
> A「追加ボタン」を押下するとテキストボックスに
>  入力したデータをグリッドに追加する
> B上記の複合でピックアップしたデータを「追加ボタン」押下によって
>  コピー追加できる
>
> 問題:Bのコピー追加の際にピックアップしきる前に
>    「追加ボタン」を押下されると
>    空のテキストボックスのまま追加されてしまう
>

グリッドとはDataGrid ですか。
この処理内容で時間がかかるとは思えませんが。
DataGrid,TextBox がデータ連結されていれば、DataGrid を選択するとすぐに
TextBox にピックアップされ、問題が発生する間もない気がします。



#当初時間がかかる処理を30分以上の長時間と勘違いしていました。(ゴメン)
#じゃんぬねっとさん、渋木宏明(ひどり)さん を混乱させてしまったみたいです。(すみません)
.NETプログラミング研究の第44,45号は参考にならないでしょうか?

http://dobon.net/vb/melma/dotnet44.txt
http://dobon.net/vb/melma/dotnet45.txt

> Methoad1はダミーのメソッドで、
> 本来呼びたいメソッドをInvokeで呼び出しています。

「本来呼びたいメソッド」が時間がかかる処理であれば、これをInvokeで呼び出したらやはりフォームは固まるでしょう。

私としては、マルチスレッドの基本を理解していないのならば、マルチスレッドプログラミングはあきらめ、別の方法を考えることをお勧めします。
お世話になります。ラフです。

みなさん貴重なご意見ありがとうございました。

結論としてはjoinは使用せず、
スレッドの開始と終了にフラグを設け
フラグがONの状態であれば他の処理は
実行しないという方法にしました。

色々と意見はあると思いますがとりあえず報告まで。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板