1

別のスレッドプールまたは専用スレッドで System.Timer コールバックを作成するにはどうすればよいですか?

バックグラウンド

System.Timer を使用する重要なアプリケーション用の軽量モニターがありますが、コールバックを ThreadPool に含めず、高い優先度で動作させる方法がわかりません。

その理由は次のとおりです。

  • 重要なアプリが応答しない場合、ThreadPool はキャンセル トークン、Thread.Abort、または Win32 Abort (ファイナライザーを実行しない) をハングしているスレッドに送信します。

  • アプリが CPU バウンドの場合、モニターへのサービス拒否を防ぐために、監視スレッドを最高の優先度で実行する必要があります。

  • スレッド数が多すぎるか、MaxThreadsの値が低すぎるために、スレッドプールが使い果たされている可能性があります

  • スレッドプールにあるスレッドに優先度を設定することはできません(AFAIK)

その結果、タイマーが必要であり、別のスレッドでコールバックする必要があると思いますが、これを実現する方法はわかりません。

別の AppDomain を作成することでこれが可能である場合、CLR では、別の AppDomain 内の他のスレッドにコマンドを発行できますか?

4

2 に答える 2

1

Thread.Sleep専用スレッドで使用することでこれを行うことができると思います。あれは:

void MonitorProc(object state)
{
    while (!ShutdownSignaled)
    {
        Thread.Sleep(MonitorFrequency);
        // Do monitor stuff here
    }
}

そのスレッドを高い優先度に設定すると、期待どおりに機能する可能性があります。ただし、それは素晴らしい解決策ではありません。

ただし、スレッドの 1 つがクラッシュして、モニターを含むアプリケーション全体が停止する可能性があるという問題がまだ残っています。

モニターを、高い優先度で実行され、ソケット、WCF、またはその他の通信チャネルを使用してメイン アプリケーションにコマンドを送信する別のアプリケーションにすることを検討してください。そうすれば、メイン アプリケーションがクラッシュしてもモニターが停止することはありません。モニターがまだ存在しない場合は、起動時にモニターを自動的に開始するようにメイン アプリケーションをコーディングできます。

しかし、あなたがリストした条件が実際に発生する可能性はどれくらいあるのだろうか. リストを下に行きましょう。

プログラムがクラッシュする可能性があるということでない限り、ここでの最初のポイントがわかりません。その場合は、別の監視アプリケーションを作成する必要があります。

アプリが CPU バウンドの場合、すべてのスレッドの優先度が同じであれば、監視スレッドはタイムスライスを取得します。他のスレッドの優先度が高い場合でも、モニターは時々タイムスライスを取得します。スレッドがリアルタイム優先でない限り。そして、あなたはそれをしたくありません

スレッドが不足している場合は、プログラムに根本的な問題があります。この問題は、実際に運用する前に発見する必要がありました。

この監視を行う最も信頼できる方法は、別のアプリケーションを使用することです。

于 2012-05-18T00:00:06.367 に答える
0

を使用してこれを行う方法を知りませんSystem.TimerSystem.Windows.Forms.Timerただし、この方法で作成した特定のスレッドでタイマーを実行して、その優先度を明示的に設定できるようにするために、に頼ることができます。

これが機能するのはTick、 a のイベントは、System.Windows.Forms.Timerそれを作成したスレッド (通常は UI スレッド) で常にトリガーされるためですが、UI を使用せずにメッセージ ループを実行するスレッドを使用して、同じことを達成することができます。

以下が許容されるかどうかを確認します。

static void Main(string[] args)
{
    var monitorContext = new System.Windows.Forms.ApplicationContext();

    var monitor = new Thread(Monitor) { Priority = ThreadPriority.Highest };

    monitor.Start(monitorContext); // Start monitor

    Thread.Sleep(5500); // ...

    monitorContext.ExitThread(); // Terminates monitor
}

public static void Monitor(object context)
{
    var timer = new System.Windows.Forms.Timer()
    {
        Enabled = true,
        Interval = 1000
    };

    timer.Tick += new EventHandler(Monitor_Tick);

    System.Windows.Forms.Application.Run(
        (System.Windows.Forms.ApplicationContext)context);
}

private static void Monitor_Tick(object sender, EventArgs e)
{
    Debug.WriteLine(
        "{0}|{1}", 
        DateTime.UtcNow.ToString(),
        Thread.CurrentThread.Priority);
}

考慮する必要がある唯一のことは、前のイベントがまだ処理されている間にティック イベントが発生した場合、それは破棄されることです。そのため、ティック イベントで行うことは、タイマーに設定された間隔よりも長くかからないようにしてください。 .

于 2012-05-17T22:20:01.480 に答える