4

一定の経過時間後に発生するように設定されたタイムアウトを使用しています。その後、コールバックを取得したいと思います。今、私はこれを使ってTimer、解雇されたときにそれ自体を処分します。

public class Timeouter
{
    public void CreateTimeout(int timeout, Action onTimeout)
    {
        Timer t = null;
        t = new Timer(_ =>
            {
                onTimeout();
                t.Dispose();
            }, new object(), timeout, Timeout.Infinite);    
    }
}

このタイマーは非常に頻繁に呼び出される可能性があり、1回だけ起動して自分自身を破棄するように多くのタイマーを設定する可能性があるため、このタイマーのリソース使用について少し心配しています。タイマーがそれであると考えると、IDisposableそれは実際にそのタスクを実行するためにある種の高価なリソースを使用していることを私に示します。

  • のリソース使用量について心配しすぎていますTimerか、それとも解決策はそのままで問題ありませんか?
  • これを行うための他のオプションはありますか?これらのタイムアウトのいくつかに対応するために、単一のタイマーを使用して、必要に応じてタイマーの開始と停止の頻度を調整する方がよいでしょうか。特定の期間が経過した後にタスクを1回実行する、他の潜在的により軽量なオプションはありますか?
4

4 に答える 4

1

答えではありませんが、長さの関係で答えとして追加しました。

サーバー/クライアント環境では、サーバーでタイマーを使用するAFAIKは最善のアプローチではありません。むしろ、シッククライアントまたはシンクライアントがある場合、サーバーで特定の操作を実行する必要がある場合は、クライアントでポーリングメカニズムを考案する必要があります。それ自体(クライアントはタイマーを設定した後に切断する可能性があり、次にタイマーを再インスタンス化して再度設定する可能性があるためなど、将来的にサーバーが使用できなくなる可能性があります(潜在的なDOS攻撃))、

または、すべてのクライアントを処理する単一のタイマー戦略を考えてください。これは、スライディング有効期限またはそれを処理するクライアント固有の戦略を実装します。

于 2012-08-24T11:26:15.753 に答える
1

もう1つのオプションは、タイムアウトするものの並べ替えられたリストを維持し、期間ではなく有効期限でリストに追加し、有効期限で並べ替えられたリストを保持し、有効期限が切れたときにリストから最初のアイテムをポップすることです。 。

もちろん、これのほとんどをセカンダリスレッドで実行し、コールバックを呼び出す必要があります。スレッドを実際に回転させ続ける必要もありません。次のタイムアウトが発生するまでの期間(少し短い)にタイムアウトを設定して、addメソッドに待機ハンドルを設定できます。タイムアウトで待機する方法の詳細については、ここを参照してください。

これがたくさんのタイマーを作成するよりも良いかどうかはわかりません。

于 2012-08-24T11:26:48.753 に答える
1

.Netには、高価な2つまたは3つのタイマークラスがあります。ただし、System.Threading.Timer使用しているクラスは非常に安価です。このクラスは、カーネルリソースを使用したり、タイムアウトを待機するスレッドをスリープ状態にしたりしません。代わりに、すべてのタイマーインスタンスに1つのスレッドのみを使用するため、数千のタイマーを簡単に使用でき、プロセッサとメモリのフットプリントを小さくすることができます。タイマーインスタンスの追跡を停止するようにシステムに通知する必要があるという理由だけで呼び出す必要がありDisposeますが、これは、これが高価なクラス/タスクであることを意味するものではありません。タイムアウトに達すると、このクラスはコールバックがスレッドによって実行されるようにスケジュールするThreadPoolため、新しいスレッドなどを開始しません。

于 2012-08-24T11:44:14.120 に答える
1

多くの間隔を計ることができる安価なタイマーを作成することは直感的に簡単です。必要なタイマーは1つだけです。最も近い期限に設定します。それがカチカチ音をたてるとき、期限が来ていたすべてのタイマーに対してコールバックまたはイベントを起動します。次に、繰り返して、次の期限のアクティブなタイマーのリストをもう一度確認します。タイマーが間隔を変更した場合は、検索をもう一度繰り返してください。

コールバックで何か潜在的に高価なことが起こる可能性があります。これに対処する最善の方法は、スレッドプールスレッドでそのコードを実行することです。

これは、システムリソースの非常に質素な使用であり、タイマーが1つだけで、スレッドが可能な限り安価です。タイマーの状態が変化するたびに少しのオーバーヘッドでそれを支払います。アクティブなタイマーのリストを調べるためのO(n)の複雑さ、SortedListを使用してそのほとんどをO(log(n))にすることができます。しかし、ああは非常に小さいです。

そのコードは自分で簡単に書くことができます。

ただし、そうする必要はありません。System.Timers.Timerはすでにそのように機能しています。助けないでください。

于 2012-08-24T12:08:46.127 に答える