- - PR -
VB.NET によるイベント ハンドラのについて
| 投稿者 | 投稿内容 | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2004-02-12 15:27
えと、できないというか、 http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vbcn7/html/vaconUnderstandingEventHandlers.asp には、 >AddHandler ステートメントと RemoveHandler ステートメントは、Handles 句よりも柔軟性があります。これらのステートメントを使用すると、実行時に 1 つ以上のイベント ハンドラに対してイベントを動的に接続および接続解除できます。また、WithEvents を使用してオブジェクト変数を宣言する必要はありません。 と書いてありますよ、ということが言いたかったのです^^; あと、タイマーを起動したままIntervalの変更は問題ないようですね^^; 申し訳ないです。 たしかに、ヘルプには何も書いてなかったのでどうかとは思ったんですが、 > タイマー起動中のインターバル変更は、「変更したときからカウントされなおします」と書いてあります。 そうだったのですね・・。 --追加
あ、これはヘルプにも書いてありますね・・ >Timer は、ユーザー定義の間隔でイベントを発生させるために使用されます。この Windows タイマは、UI スレッドを使用して処理を実行するシングルスレッド環境に合わせて設計されています。ユーザー コードには利用できる UI メッセージ ポンプが必要です。また、このコードは必ず同じスレッドから操作し、別のスレッドに対する呼び出しをマーシャリングする必要があります。 の部分でしょうか。 [ メッセージ編集済み 編集者: りばぁ 編集日時 2004-02-12 15:41 ] | ||||||||||||
|
投稿日時: 2004-02-12 15:43
Process.SynchronizingObjectのヘルプを見て納得です。 勉強になりました。 | ||||||||||||
|
投稿日時: 2004-02-12 16:02
解決したようでなによりです。 ところで、本題とは関係ないんですが、この記述はあまりよろしくないのではないでしょうか。 変数clsTestはButton1_Clickメソッド内のローカル変数なので、 Actionメソッドを実行し、メソッドを抜けた時点でNothingになるため、 このclsSampleクラスのインスタンスの参照を保持するものはなくなると思います。 となると、evtEventイベントが発生する前に、ガベージコレクションが働くと、 その後、evtEventイベントは二度と発生しないことになります。 | ||||||||||||
|
投稿日時: 2004-02-12 17:10
みなさん、ありがとうございます。
返答遅れてすみません。 実はBBSに2ページ目があるとは気づかなかったもので・・・ 面目ないですm(__)m
Exitedが原因だったのですね!! Process.SynchronizingObjectは大変勉強になりました。 完全に理解できた訳ではないのでこれからHelpと睨めっこしようと おもいます(笑
詳しくはこれから調べて検証しないといけないのですが メソッドを抜けた時点でNothingになってもプロセスが残っている為、 プロセスが無くなるまでガベージコレクションは働かない様な気がします。 ただ確証がないのでローカル変数で使わない方向にするかもしれませんです。 今回はほんと勉強になりました。 お時間を割いて頂き、皆さま本当にありがとうございました。 | ||||||||||||
|
投稿日時: 2004-02-12 18:09
その認識は違います。ガベージコレクションは、「いつ動くかわかりません」。システム(.NET Framework?)がマネージメモリが足りないと判断した時点で動きます。または、明示的にGC.Collectメソッドを呼び出すか。 #だから、AddHandlerができないとエラーがでた、のだと思っていたのだが。。。 | ||||||||||||
|
投稿日時: 2004-02-12 19:29
<今回のまとめ>
皆様のおかげで無事成功しました。ありがとうございます。 SetSynchronizingObjectを使用たソースを載せておきます。 以下変更コード↓↓↓
Jitta様、返信ありがとうございます。
確かにGCはいつ動くか分かりませんね^^; クラスのデバック中にいきなりFinalize走ることもありますし。 でも、確かManageObjectで参照があればGCで開放されなかったような気がします。 以下参考文献↓↓↓ http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/cpref/html/frlrfSystemGCClassTopic.asp 上記URLから抜粋
上記「コレクションの実行中、マネージ コード内のオブジェクトへの 1 つ以上の参照が見つかった場合、ガベージ コレクタはそのオブジェクトを解放しません。」 とあります。 今回はclsSampleを開放しても プロセスの参照が残っている・プロセスはManageObjectの為 GCでの開放は行われないと認識しています。 検証としては不十分ですがプロセスが開放された時、ランダムでFinalizeが走るのを確認しています。 何分、GCは勉強中なので間違っていたらすみません。 | ||||||||||||
|
投稿日時: 2004-02-12 20:08
MSDN ライブラリ 「Visual Basic 言語の仕様 - 6.9 デリゲート」より
ということらしいので、clsSample クラスの Action メソッドで >AddHandler SampleProcess.Exited, AddressOf processExited をしているため、clsSample クラスのインスタンスはデリゲートに格納されているらしいです。 つまり、SampleProcess が実行中である限り、ガベージコレクションの 対象にはならないと思われます。 >なっくさんへ 解決したあとで申し訳ないのですが、^^; System.Windows.Forms.Timer クラスの代わりに System.Timers.Timer クラスを使うという手も一応はあると思います。 #一応は大丈夫っぽいです。 | ||||||||||||
|
投稿日時: 2004-02-12 20:33
えーここの辺りを確認するには、最終的に参照がルートにつながっているかを考える必要があります。 >AddHandler SampleProcess.Exited, AddressOf processExited これにより、SampleProcessオブジェクトには、clsSampleへの参照が含まれていることになります。 したがって、SampleProcessオブジェクトが生きている(ここでは破棄されたという意味ではなく、参照が残っているという意味で)限り、clsSampleは生きていることになります。 では、SampleProcessオブジェクトの参照は誰が保持しているでしょうか?clsSample自身ですね。すなわち循環参照であり、ルートにつながっていないため、これ自体は意味を持ちません では、clsSampleを誰か他の場所から参照しているでしょうか? Button1_Clickメソッドが終了すると、もはや誰も参照していませんね。 さて、Button1_Clickメソッドが終了した後で、たまたまGCが発生したとします。 ここでGCは、ルートから全てのオブジェクトをたどって、オブジェクトが有効か調べます。どこからもSampleProcessおよびclsSampleにはたどり着きませんので、GCの対象になります。 というわけで、やっぱりまずいんではと思うわけですが、どこかに見落としがあるような気がしないでもありません。 まあ、正直なところで言うと、「怪しい or 自信のないことはするな」ということで、私はやらないです… | ||||||||||||
