3

私のアプリケーションには、現在、次のように長時間実行されているスレッドに実装されている「ハートビート」機能があります(擬似コード)。

while (shouldBeRunning)
{
    Thread.Sleep(smallInterval);

    if (DateTime.UtcNow - lastHeartbeat > heartbeatInterval)
    {
        sendHeartbeat();
        lastHeartbeat = DateTime.UtcNow;
    } 
}

さて、私のアプリケーションが集中的なCPU時間(CPUが90%以上占有されている数分間の重い計算)を経験しているとき、たとえsmallInterval << heartbeatIntervalであっても、ハートビートが遅れることがあります。

いくつかの数値を処理するには:heartbeatIntervalは60秒、lastHeartbeatは0.1秒、報告される遅延は最大15秒です。つまり、私の理解では、CPUが非常にビジーの場合、Sleep(10)はSleep(15000)のように持続する可能性があります。

スレッドの優先度をAboveNormalとして設定しようとしましたが、このような問題を回避するためにデザインを改善するにはどうすればよいですか?

4

3 に答える 3

4

これにタイマーを使用できない理由はありますか?あなたが使うことができる3つの種類があります、そして、私は通常のために行きSystem.Timers.Timerます。ただし、次の記事では違いについて説明します。

http://msdn.microsoft.com/en-us/magazine/cc164015.aspx

基本的に、タイマーを使用すると、定期的な間隔でタイマーを設定し、その期間が過ぎたときにイベントを発生させることができます。次に、を呼び出すデリゲートを使用してイベントをサブスクライブできますsendHeartbeat()

タイマーは、スリープ状態のスレッドと同じようにCPU負荷の影響を受けないため、より効果的に機能するはずです。コードの点で少しすっきりしているという利点があり(タイマーの設定は非常にシンプルで読みやすい)、予備のスレッドがないという利点があります。

于 2012-02-22T17:31:25.387 に答える
3

あなたはタイマークラスの1つを再発明しようとしているようです。

たとえば、 System.Timers.Timerを使用するのはどうですか?

var timer = new System.Timers.Timer(smallInterval);
timer.Elapsed += (s, a) => sendHeartbeat;
timer.Enabled = true;

ここでの問題の1つは、推測では、CPUに負荷がかかっているときにスレッドがスケジュールされる頻度です。タイマーの実装は、本質的にシングルスレッドとブロックです。フレームワークタイマーの1つに移動すると、(上記のタイマーを例にとると)経過したイベントがスレッドプールスレッドで発生するため、これを軽減する必要があります。

于 2012-02-22T17:33:17.600 に答える
2

残念ながら、WindowsはリアルタイムOSではないため、スレッドがいつ実行されるかについての保証はほとんどありません。スレッドを次にThread.Sleep ()ウェイクアップする必要がある最も早い時間をスケジュールするのは、空きタイムスライスがあるときにスレッドをウェイクアップするのはOS次第です。スリープ状態のスレッドをウェイクアップするための正確な基準はおそらく文書化されていないため、Windowのカーネルチームは適切と思われる実装を変更できます。

タイマーの期限が切れた後もハートビートスレッドをアクティブ化する必要があるため、Timerオブジェクトがこれを解決するかどうかはわかりません。

1つの解決策は、ハートビートスレッドの優先度を上げて、より頻繁に実行される機会を得ることです。

ただし、ハートビートは通常、サブシステムが無限ループに陥ったかどうかを判断するために使用されるため、通常、優先度は低くなります。CPUを集中的に使用するセクションがある場合は、Thread.Sleep (0)重要なポイントで実行して、優先度の低いスレッドを実行できるようにします。

于 2012-02-22T17:43:45.050 に答える