8

Compact Framework 2、SP2でC#を使用しています。

デバイスのOSは、私のアプリケーションで起動するように設定されています。アプリケーションを「Loader.exe」と呼びましょう。

ローダーは単純にこれです。必要に応じて、ロード中のステータスメッセージを表示する単一のプレーンフォーム(エラーと例外メッセージ、または「アプリケーションの開始[xyz]」があるという素人の用語)、およびバックグラウンドで実行されているステートマシン基本的なフルスクリーンフォームが表示されます。

したがって、ローダーのフォームのコンストラクターの最後には、次のものがあります。

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初期化スレッドを開始しています...」というメッセージを表示し続けました。

これは、スレッドタイマーが必要なときに実行されていないことを示しています。
私の理論では、タイマーがコールバックをトリガーする前にガベージコレクションされています。つまり、タイマーがグローバルであり、RunStateMachineに到達したときに明示的に破棄された場合、完全に実行されます...しかし、これが1か月後に断続的に発生するのを見つけただけで、解決したとは思いません。

考え?

4

1 に答える 1

10

私の理論は、タイマーがコールバックをトリガーする前にガベージコレクションされているということです。これは、タイマーがグローバルであり、RunStateMachine に到達したときに明示的に破棄された場合、完全に実行されることを意味します...しかし、今から 1 か月後に断続的に発生することを見つけるためだけに解決したとは思いたくありません。

これがあなたの問題であることを確認したいようです。はい、これが問題です。

タイマーは、二度​​と使用されないローカル変数に格納されます。これにより、GC の対象となります。タイマーのGC'ingは、タイマーが無効になるファイナライズにつながります。

タイマーをフォーム クラスのインスタンス フィールドに格納し、コールバックが発生したらそこから削除することをお勧めします。

于 2012-10-03T15:55:09.717 に答える