- - PR -
2つのタイマー処理で、画面が応答なしになる
投稿者 | 投稿内容 | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-03-02 00:33
Threading.Timerクラスを使って定期的に画面表示をするアプリを作っています。
まず、メインフォームが2秒ごとに画面表示を行い、メインフォームにつけているボタンを押すことで表示されるモードレスダイアログでも2秒ごとに画面表示を更新します。 モードレスダイアログには閉じるためのボタンをつけているのですが、ボタンを押しても反応がありません。 それどころか、メインフォームも固まっているかのように白くなります。 解決したいのですが、原因が分からないので困っています。 インターバル2秒くらいのタイマーを2つ使ったくらいで、ビジーになるとは思えないんですが・・・。 何が原因と考えられるでしょうか? 気になるのは、メインフォームでインスタンス化したクラスをダイアログでも使ってることです。 2つの画面で、このクラスのメソッド内で生成されたデータをもらっています。 | ||||||||||||||||||||
|
投稿日時: 2007-03-02 09:31
画面と関連する使い方でタイマーを使うのに System.Windows.Forms.Timerを使わない理由は何でしょうか? (明確な理由があるのであれば別ですが、特に理由がなければWindows.Formsのタイマーを使う方がよいと思います) IT:.NET Tips タイマにより一定時間間隔で処理を行うには?(Windowsタイマ編) Threading.Timerを使うのであれば、UIスレッドとの同期を取る必要があるのですが、 以下のあたりを把握できているか確認してください。 IT:.NET Tips Windowsフォームで別スレッドからコントロールを操作するには? 上記のコメントはあやしそうかな?と思っただけで、解決策に結びつくかどうかはわかりません。 ご提示いただいている情報では、具体的な実現方法の大部分がわからないので、 アドバイスが非常に難しいです。 小さいプロジェクトを作成して、同じ現象を再現させようとしてみてください。 あるいは、今現在のソースコードを部分的にコメントアウトするなどして、 現象が起きる最小限のコードを見極めてください。 その最小限のコードを提示していただくのが最も手っ取り早いと思います。 #まぁその解析の過程で解決してしまう可能性の方が大きいですが。 | ||||||||||||||||||||
|
投稿日時: 2007-03-03 12:11
インターバルを変える機能がありますので、短いインターバルが指定された場合でも対応できるようにするためです。
ちゃんとできています。
問題のアプリとまったく同じコードではないですが、似たようなコードを組んでみても ビジーになるようなことはありませんでした。 以下にコードを示します。 親フォーム
モードレスダイアログ
上記コードでは足し算とか乱数の表示のみですが、 実際のアプリでは、親とダイアログで同じインスタンスからデータをもらっています。 もらうデータの件数は1〜数千件です。 データをもらうメソッドは異なりますが、やはりそのメソッドの処理が影響しているのでしょうか? | ||||||||||||||||||||
|
投稿日時: 2007-03-04 00:21
このデータをもらって何らかの処理してるのはコールバック側でしょうか? それとも画面更新側でしょうか?あるいは両方でしょうか? このデータのアクセス(処理)は何らかの方法で同期しているでしょうか? あるいはそれぞれのメソッドで同期は取らずに処理しているでしょうか? データの処理あるいは画面への表示?処理は2秒よりずっと短い時間しかかからない処理でしょうか? 結構時間がかかる処理でしょうか? 場合によっては2秒以上かかることもあるというくらいの処理でしょうか? タイマーでの処理と画面表示の処理は、例のコードのように順に1回ずつだけでしょうか? あるいはレコードごとなど、処理と表示を繰り返す感じでしょうか? | ||||||||||||||||||||
|
投稿日時: 2007-03-04 00:37
コールバック側??? 記事に載せたコードで言うと、UpdateTextメソッドやDisplayTextメソッドにあたります。
同期はとっていません。
親とダイアログから呼ばれるメソッドでは、複雑な計算を行っています。 その数は50くらいです。 計算の対象となるデータの件数は多くても数千件です。 2秒はかからないと思うのですが…。
親、ダイアログ共にタイマーで、データをもらう→画面表示更新 となっています。 | ||||||||||||||||||||
|
投稿日時: 2007-03-04 02:34
System.Windows.Forms.Timerに置き換えてみましたか?System.Windows.Forms.Timerは 「フォーム アプリケーションで使用できるように最適化」されているので、これを使ったら 問題が解決される可能性もなくはないです。
というか、「問題の現象が再現する」最小のコードを示すべきでは?
というか、その部分だけ切り出して、計測してみればいいのでは? | ||||||||||||||||||||
|
投稿日時: 2007-03-06 00:13
親とダイアログそれぞれの処理がどのような順序で実行されているかログに出してみました。
どうやら定期的に動いていないようです。 (1) 親フォームの処理 (2) ダイアログの処理 (3) 親フォームの処理 (4) 親フォームの処理 (5) ダイアログの処理 (6) 親フォームの処理 (7) 親フォームの処理 : こんな感じでした。 親フォームのタイマーインターバルはダイアログのタイマーインターバルの半分であるにもかかわらずです。 ダイアログの処理が完了するまでに4秒かかっていました。 その間、親フォームには制御が渡っていません。 そして、ダイアログ側の処理が終わった(?)ら、親フォームの処理が続けて実行されました。 ダイアログ側のタイマーで呼ばれるメソッドには、いろいろコードを書いてますが、 それらのコード自体には時間がかかっていないみたいでした。(ログで確認) しかし、ダイアログ側のメソッドに入った直後とメソッドを出る直前の経過時間が約4秒なんです。 ダイアログ側のメソッドを出る直前では、PanelのRefreshをしているだけなんですけどね。 まさかこれが原因・・・? ちなみに、ダイアログ側のタイマーをThreading.TimerクラスからForms.Timerクラスに変えても同じでした。 | ||||||||||||||||||||
|
投稿日時: 2007-03-06 02:39
別スレッドからPanelを直接操作した場合の動作は保障されませんよ。 ぁ、でもそれは「ちゃんとできています。 」なんでした。。 やはり、同じインスタンスからデータを云々、ていうのが原因なんでしょうかね。 |