- - PR -
スレッドタイマにて一定間隔で呼び出すメソッド内のDLL関数が実行されない
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-06-03 19:05
VC#2005で開発しています。
フォームのボタンを押すと、処理が実行されるとともに スレッドにてステータスを監視する、というアプリを実装しています。 スレッド内のステータス監視は、処理が実行されているあいだに 10ms程度の間隔で、繰り返し行いたいと考えてます。 そこで、ボタン押下時にスレッドタイマを起動させ、処理完了 後にdisposeすることとしました。 (timerCallBackをdelegateとして、timerをnewするときに左記の delegateと、開始までの時間、繰り返し間隔等を引数にしてます) http://www.atmarkit.co.jp/fdotnet/dotnettips/373threadtimer/threadtimer.html ところが、delegateで渡したメソッド内のステータス監視関数が 実行されないようなのです。ブレークポイントを置いてみますと、 同関数の直前までは処理が問題なく進んでいます。しかし、同関数は 実行されず、もちろん戻値は返しませんし、try-catchでの 例外処理にもかかりません。 同関数は、別クラス内で定義されていて、DLLインポート されたものです。 同関数をコメントアウトすると、残りのメソッド内処理は行われます。 上記について、どのあたりに問題があるのでしょうか。ご教授願います。 ※記載に不足がありましたら指摘ねがいます。 | ||||||||
|
投稿日時: 2008-06-03 23:06
バグがあるんでしょうけど、コードがないとさすがに難しいですね。
_________________ 囚人のジレンマな日々 | ||||||||
|
投稿日時: 2008-06-03 23:16
「同関数は実行され」ていないのは確かでしょうか?戻ってこないことは確認されているとは思いますが、実行されていないことを確認することは難しいのではないでしょうか。 ひとつの推理ですが、その関数がメッセージループを内部に持っていて、関数が実行されて関数の中には入っているけど、メッセージループがメッセージを処理するためそこから抜け出せない状態になっているということはないでしょうか。私は自分ではそういうのは外側でやりたいので、中には持たせませんが、昔から、中に持たせているような API は巷では結構見かけます。 あとは、なにかバグがあって関数を呼ぶとスタックを壊しているなどでしょうか。 「スレッド・タイマ」を使われているそうですが、ためしに「サーバベース・タイマ」を使い、「タイマ・メソッド」がUIスレッドで動くようにしてみてはどうでしょうか。 | ||||||||
|
投稿日時: 2008-06-04 00:49
Timerのインスタンスをローカルで作成してそのままメソッドを抜けていて、参照を保存してないとかないですか?
記事のコードも実際には問題あります。 ※記事の方はデバッガ上では普通に動いてしまうでしょうけど System.Threading.Timerの解説のところ >Timer を使用している間は、このクラスへの参照を保持しておく必要があります。他のマネージ オブジェクトと同様、まったく参照されていない場合、Timer はガベージ コレクションの対象となります。Timer がアクティブであっても、ガベージ コレクションの対象から除外されることはありません。 --追記 とと、失礼、処理完了後にDisposeって書かれてますね… やっぱりある程度ソースがないとわからなさそうです… [ メッセージ編集済み 編集者: なちゃ 編集日時 2008-06-04 00:55 ] | ||||||||
|
投稿日時: 2008-06-04 09:53
皆様、ご回答いただきありがとうございます。
対象部分のコードを以下に示したいと思います。 //-------以下、コード-----------------------------------//
上記のような感じです。 ちなみに、スレッドタイマを使わずに、1回だけステータスの監視 をするようなコード(ProcClassのhoge関数内に dllStart、dllCheckStatusを続けて実行)であれば問題なく動作します。 ので、dllインポートした関数内から処理が抜けられない、といった 問題ではないと考えます。 が、狙いはdllStart実行中に繰り返しdllCheckStatusを行いたい、 ということです。 なちゃ様指摘の「参照を保持しておく」の意味がよくわかっていません。 あわせてご教授願えないでしょうか。 以上、よろしくお願いいたします。 | ||||||||
|
投稿日時: 2008-06-04 10:01
そりゃタイマを Dispose したら動いてたタイマは止まるでしょう。
| ||||||||
|
投稿日時: 2008-06-04 10:13
Hongliang様、ご回答いただきありがとうございます。
class ProcClassのhoge関数内で実行している dllStartは、完了に数秒を要します。ので、その前に スレッドタイマにてステータスを監視するdllCheckStatus を繰り返し実行するようにしておき、dllStartが完了 すれば、タイマは不要ということでDisposeしている、 という意図でこのようなコードにしています。 (この意図からして誤っているのでしょうか?) ちなみに、Disposeをしなかったとしても、dllCheckStatus は実行されませんで(実行直前までいくことはブレークポイントで 確認しています)、dllStartを実行完了後、フォームに 戻ってしまいます。 以上、よろしくお願いいたします。 | ||||||||
|
投稿日時: 2008-06-04 15:16
目論見が良く分からないのですが、いきなり 10ミリ秒間隔で試さないといけないのでしょうか?最初は10〜100秒間隔くらいで試したほうがデバッグしやすいと思うのですが。 System.Threading.Timer を使ったマルチスレッドは私はあまり良く分からないのですが、タイマー一般の話で言うと、間隔が短いと、「タイマ・メソッド」が呼ばれて、そこから抜けないうちに、あらたに「タイマ・メソッド」が呼ばれ、「タイマ・メソッド」が多重に動いてしまう、ということになる可能性はないですか? 「タイマ・メソッド」の問題ではなく DLL の関数の問題であることは確かなのでしょうか?DLL の関数を使わず、ダミーの .NET の関数を使った場合はちゃんと動くのでしょうか? |