- - PR -
イベントハンドラーの中でさらにイベントを起こすと、再帰的に呼び出されてしまう
«前のページへ
1|2|3|4
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-04-13 19:33
Application.Idle を使ってみました。イベントハンドラーは Application_Idle というメソッドです。自前でキューを持っており、イベントをレイズしたいときには、一旦キューに追加し、その後 Application_Idle が動いたときに、実際にイベントがレイズされます。 この動きは、button1 を押した場合は、私の目論見どおり動きました。 一方、button2 も作り、これを押すと、タイマーを起動して、3秒後にキューに入れるようになっています。この場合、問題があって Application_Idle が呼ばれなくなるのです。フォームの上でマウスを動かしていたり、なにかキーを押せば Application_Idle が頻繁に起こるのですが、完全にじっとしていると Application_Idle が呼ばれません。(タイマーを使ったのは、テスト用に、ボタンを押した後にじっとするまでの余裕を作るためです。) 要は、好きなタイミングで Application_Idle が呼ばれるようにしたいのですが、その手段が分かりません。 Application クラスに RaiseIdle という名前のメソッドがあるのをたまたま見つけて、とりあえず呼んでみましたが、変化はないようでした。 まあ、なにかフォーム上のコントロールをプログラムからごにょごにょいじれば Application_Idle が起こるとは思いますが、なんだかスマートではないなあと思いました。 なお、タイマーのプロパティー SynchronizingObject にフォームのインスタンスを指定して、UI のスレッドでタイマーを動かせば Application_Idle は起きました。
(以下、追記。) 話がややこしくなってすみません。ここでのタイマーは、マウスイベントやキーイベントのほとぼりが冷めるまで待つまでのためだけの、一時的なテスト用のものです。 キューの List に要素を追加しただけでは、当然のことながらだれも感づいてくれず、したがって Application_Idle が呼ばれないわけですが、この辺の仕組みをどう解決すればよいかで悩んでいます。 [ メッセージ編集済み 編集者: unibon 編集日時 2008-04-13 19:43 ] | ||||||||
|
投稿日時: 2008-04-13 20:28
すみません。自分でも話がややこしくなって良く理解できていないのですが、先日挙げたAさん、Bさん、Cさん、の例は適切ではなかったかもしれません。 私のアプリケーションでは、Aさん、Bさん、Cさん、の3つのインスタンスを区別したいのではないと思います。マルチキャストはしたいのですが。 | ||||||||
|
投稿日時: 2008-04-13 22:59
Idleはその名の通り、Idleになったとき=メッセージが空になったときに 一度だけ起きるイベントです。 定期的にイベントを発生させたいならTimerを、 全てのイベントが終了して暇になったのを知りたいときにはIdleを。 よく考えればわかると思いますが、 イベントドリブン的には十分なイベントがそろっています。 内部でループで条件待ちをしたり、 WaitHandleを使ったり、 Thread.Sleepで他のアプリに時間の解放をしたり、 DoEventsを使って危険なメッセージポンピングをしたり… そういったことは全く必要ありません。 TimerやApplication.Idleを使うことで レスポンスもパフォーマンスもよく、無駄のない、 「よいアプリケーション」を組むのは理論上可能です。 問題は、イベントの使い方、Idleの使い方、 そういったパラダイムが逐次実行の概念と合わず、 少しわかりづらいという点です。
最初に言ったように、 イベントドリブンというものをもう一度よく考え、 「好きなタイミング」というのが「いつ」なのか、 よく考えてみるとよいでしょう。 | ||||||||
|
投稿日時: 2008-04-14 07:24
Application.Idle というものを知りませんが…。wikipediaの説明を読むと興味深いことが書いてありますね。シングルスレッドなのにハンドラのコード実行中に他に制御が移るってことなのかな…。よく分かりません。今度、暇を見つけて試してみよう。。
で、unibon さんの書いてる症状を見ると、なんか GetMessage() なり、WaitMessage() なりでメッセージを待っているときと似ているように思います。これって Windows アプリケーションとして当たり前のことですよね。(マウス操作など)何もしなければ、なにも起こらない。でも、Application.Idle というハンドラが発生しなくなっても良いものなのかと疑問に思います。 Application.Idle って内部的にはどうやって実装されてるんでしょうね。メッセージループで、メッセージが着信したあとで、GetQueueStatus() でキューの状態を調べて空なら Application.Idle ハンドラを呼んでるとか? それで、メッセージが着信しない状況では動かなくなってしまうのかなあと予想。 |
«前のページへ
1|2|3|4