System.Threading.Timerが起動しないのですか?
-
13-12-2019 - |
質問
C#をコンパクトフレームワーク2、SP2に使用しています。
私のアプリケーションと起動するように設定されているように設定されていましたが、アプリケーション "loader.exe"を呼び出しましょう。
ローダはこれです。必要に応じて、ロード中のステータスメッセージを表示する単一のプレーンなフォーム(エラーと例外メッセージのレイマンの用語、または「アプリケーション[XYZ]」)とステートマシンが実行されます。基本的なフルスクリーンフォームが表示されている間、バックグラウンドで。
SO Loaderのフォームのコンストラクタは、非常に end:
で次のものを持っています。try
{
label1.Text = "Starting GUI Init Thread..."; //debug only message
System.Threading.Timer guiInit = new System.Threading.Timer(
RunStateMachine, null, 2000, System.Threading.Timeout.Infinite
);
//callback: RunStateMachine, null argument
//initial callback is 2000ms from this point, and doesn't run again.
}
catch (Exception ex1)
{
label1.Text = "GUI Init Error 2";
Failure_Label.Text = ex1.Message;
}
.
と "runStateMachine"はUIとは異なるスレッドで動作し、フォームが表示されることを許可し、runstateMachineがメッセージの更新などの形式と対話する必要がある場合は、ifを使用する関数を呼び出します(this.invokeRequired ){this.invoke(...);} else {...}
だから、私の問題?
断続的に、私のプログラムはハングアップし、タイマーがコールバックを起動しなかったためです。私は上記のTryブロック内のデバッグメッセージで、「RunStateMachine」の非常に始めているメッセージを含めて、他の多くの場所と共に追加された。最終的には、私のプログラムは「GUI INITスレッドを起動します...」
これは、スレッドタイマーがそれを必要とする 1 時間を実行していないことを私に知らせます。
私の理論は、コールバックをトリガーするタイマーの前にガベージ収集されているということです。それは、タイマーがグローバルされていたら、RunstateMachineに到達したときに明示的に処分された場合、それは完全に実行されることを明示的に処分しています...しかし、私は今から断続的に断続的に出てくるのを見つけるためにそれを解決したくないと思っています。
思考?
解決
私の理論は、タイマーの前にゴミ収集されているということです。 コールバックをトリガーします。それはタイマーがグローバルされた場合、 それから私がランテテムマシンに着くときに明示的に処分された、 完璧に走る...しかし、私はそれを解決したばかりで解決したくない これは今から断続的に出てきています。
これがあなたの問題であることを確認したいようです。はい、これは問題です。
タイマーは、再び使用されていないローカル変数に格納されています。これはGCの対象となります。タイマーのGCのGCは、無効にされるタイマーにつながるファイナライズをもたらします。
私はあなたがフォームクラスのインスタンスフィールドにタイマーを保存し、コールバックが発生したらそこからそれを削除します。