- PR -

スレッドでのDoEvents

投稿者投稿内容
コウイチ
常連さん
会議室デビュー日: 2003/11/04
投稿数: 48
投稿日時: 2005-10-18 12:06
アプリでテーブルの索引の構築を行っています。
その構築に20分ほど処理に時間がかかるため、その間フォームが固まってしまいます。
そこで、
System.Windows.Forms.Application.DoEvents();
を別スレッドで、一定時間ごとに呼び出そうと思い、
以下のようにしたのですがフォームが固まったままになります。

static void Main()
{
 TimerCallback timerCallback = new TimerCallback(ThreadMethod);
 System.Threading.Timer timer = new System.Threading.Timer(timerCallback, null, 0, 500);

 Application.Run(new MainForm());  // 索引の構築処理

 timer.Dispose();
}
private static void ThreadMethod(object state)
{
 System.Windows.Forms.Application.DoEvents();
}

実行してみると索引構築中でもDoEventsは一定時間ごとに呼び出されていますが、
フォームは固まったままなので、別スレッドで呼び出しているから???
と思ったのですが合ってるでしょうか?
合ってるとして、どのようにすれば本スレッド?に対して
System.Windows.Forms.Application.DoEvents();
を呼び出せるのでしょうか?

よろしくお願いします。m(_ _)m

開発環境:(C#、VS.NET2003)
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-10-18 12:26
Application.DoEvents メソッドを使わずとも、
System.Threading.Thread.Join メソッドを用いて、
終了するまでに適宜本スレッドに処理を返すとか...

  Thread.Join メソッド

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2005-10-18 12:36
こんにちは。
私は.NET素人なので間違っていたらスイマセン。

引用:

コウイチさんの書き込み (2005-10-18 12:06) より:

実行してみると索引構築中でもDoEventsは一定時間ごとに呼び出されていますが、
フォームは固まったままなので、別スレッドで呼び出しているから???
と思ったのですが合ってるでしょうか?



メッセージキューはUIを持つスレッド毎に作成されます。

つまり別スレッドから
System.Windows.Forms.Application.DoEvents();
を呼び出しても、そのスレッド自身がもつメッセージキューがポンプされるだけで
メインスレッドのメッセージポンプは行われないと思います。

引用:

アプリでテーブルの索引の構築を行っています。
その構築に20分ほど処理に時間がかかるため、その間フォームが固まってしまいます。



こちらの長時間かかる処理を、別スレッドを作って処理すればよろしいのではないでしょうか。
コウイチ
常連さん
会議室デビュー日: 2003/11/04
投稿数: 48
投稿日時: 2005-10-18 23:41
じゃんぬさん、Tdnr_Symさん
返信ありがとうございます。
返事遅くなってすみません。

[Tdnr_Symさん]
> こちらの長時間かかる処理を、別スレッドを作って処理すればよろしいのではないでしょうか。

[じゃんぬさん]
> Application.DoEvents メソッドを使わずとも、
> System.Threading.Thread.Join メソッドを用いて、
> 終了するまでに適宜本スレッドに処理を返すとか...

長時間かかる処理(CreateIndex)を別スレッド(thread)でスタートして、

Thread thread = new Thread(new ThreadStart(CreateIndex));
thread.Start();
flag = false;
while (!flag)
{
 flag = thread.join(1000);
}

と上記のような感じでループさせて、
このスレッド(索引の構築)が終わるまで次に進ませないようにするということで、
本スレッドに処理を返すの意味は合っているでしょうか?


よろしくお願いします。m(_ _)m
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2005-10-19 08:57
引用:

コウイチさんの書き込み (2005-10-18 23:41) より:

このスレッド(索引の構築)が終わるまで次に進ませないようにするということで、
本スレッドに処理を返すの意味は合っているでしょうか?


ええ、そういうことです。
手軽にやろうとするとそうなります。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
コウイチ
常連さん
会議室デビュー日: 2003/11/04
投稿数: 48
投稿日時: 2005-10-19 09:18
じゃんぬさん、返信ありがとうございます。
この方法で試してみようと思います。

じゃんぬさん、Tdnr_Symさん ありがとうございました。
また質問のときは、よろしくお願いしますm(_ _)m
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2005-10-19 09:53
こんにちは。

引用:

コウイチさんの書き込み (2005-10-18 23:41) より:

長時間かかる処理(CreateIndex)を別スレッド(thread)でスタートして、

Thread thread = new Thread(new ThreadStart(CreateIndex));
thread.Start();
flag = false;
while (!flag)
{
 flag = thread.join(1000);
}

と上記のような感じでループさせて、
このスレッド(索引の構築)が終わるまで次に進ませないようにするということで、
本スレッドに処理を返すの意味は合っているでしょうか?



あれ、フォームが固まらないようにするんではなかったでしたっけ!?

引用:

コウイチさんの書き込み (2005-10-18 12:06) より:
フォームが固まったままになります。



フォームが固まらないようにするには

コード:
bool flag;
Thread thread = new Thread(new ThreadStart(CreateIndex)); 
thread.Start(); 
flag = false; 
while (!flag) 
{ 
	flag = thread.Join(0); 	// (*1)
	System.Windows.Forms.Application.DoEvents();	// (*2)
}



のように、DoEvents()をループの中で呼んでやらないといけないですよね。(*2)
スレッドの終了確認(Join)も長い間(1000ミリ秒間)ブロックするとスムーズにメッセージループがまわらないので、短くしましょう。(*1)

あとbutton押下が上記処理のトリガーになっている場合は、再入を防ぐために
処理前にbuttonのEnabledをfalseにしておきましょう。
コウイチ
常連さん
会議室デビュー日: 2003/11/04
投稿数: 48
投稿日時: 2005-10-20 12:08
Tdnr_Sym さん、ありがとうございます。

ループ内に
Application.DoEvents();
を書かないとフォームは固まったままでした。

引用:

じゃんぬねっとさんの書き込み (2005-10-18 12:26) より:
Application.DoEvents メソッドを使わずとも、
System.Threading.Thread.Join メソッドを用いて、
終了するまでに適宜本スレッドに処理を返すとか...

固まらなくはなったのですが、この記事の内容が気になります。
DoEvents メソッドを使わないでも、Thread.Join メソッドだけで
フォームを固まらないようにする方法=手軽出ない方法だと思うのですが・・・。
調べてはみたのですが、その方法がわかりません。(見つけられません><)
参考にできるサイト等あれば教えて頂けないでしょうか?

よろしくお願いします。m(_ _)m

スキルアップ/キャリアアップ(JOB@IT)