7

タイマーを使用するクラスがあります。このクラスはを実装しIDisposeます。Disposeタイマーが再び起動しなくなるまで、メソッドで待機したいと思います。

私はそれを次のように実装します:

private void TimerElapsed(object state)
{
    // do not execute the callback if one callback is still executing
    if (Interlocked.Exchange(ref _timerIsExecuting, 1) == 1) 
        return;

    try
    {
        _callback();
    }
    finally
    {
        Interlocked.Exchange(ref _timerIsExecuting, 0);
    }
}

public void Dispose()
{
    if (Interlocked.Exchange(ref _isDisposing, 1) == 1)
        return;

    _timer.Dispose();

    // wait until the callback is not executing anymore, if it was
    while (_timerIsExecuting == 0) 
    { }

    _callback = null;
}

この実装は正しいですか?timerIsExecuting == 0_が不可分操作であるかどうかという質問に主に依存すると思います。または、を使用する必要がありますかWaitHandle。私にとっては、コードが不必要に複雑になるようです...

私はマルチスレッドの専門家ではないので、アドバイスをいただければ幸いです。

4

3 に答える 3

10

使用しない理由がない限りSystem.Threading.Timer これにはDispose待機ハンドルを持つメソッドがあります

そして、あなたは次のようなことができます、

private readonly Timer Timer;
private readonly ManualResetEvent TimerDisposed;
public Constructor()
{
    Timer = ....;
    TimerDisposed = new ManualResetEvent(false);
}

public void Dispose()
{
    Timer.Dispose(TimerDisposed);
    TimerDisposed.WaitOne();
    TimerDisposed.Dispose();
}
于 2012-11-15T12:30:50.650 に答える
-1

タイマーを手動で破棄する必要があるのはなぜですか? 他に解決策はありませんか。経験則として、この仕事は GAC に任せたほうがよいでしょう。– LMB 56 分前

ASP.NET アプリケーションを開発しています。タイマーは、HttpApplication の Dispose の呼び出しで破棄されます。理由: コールバックがロギング システムにアクセスできた可能性があります。したがって、ロギングシステムを破棄する前に、タイマーが破棄されていることを確認する必要があります。– SACO 50 分前

タイマーをポーデューサーとして使用するプロデューサー/コンシューマー パターンがあるようです。

この場合、ConcurrentQueue() を作成し、タイマーがキューにジョブをエンキューするようにします。次に、別の安全なスレッドを使用してジョブを読み取り、実行します。

これにより、ジョブが別のジョブと重複するのを防ぐことができます。これは、コードの要件と思われます。また、yourQueue == nullジョブを追加する前にできるため、タイマーの破棄の問題も解決します。

これは最高のデザインです。

もう 1 つのシンプルだが堅牢ではない解決策は、コールバックをtryブロックで実行することです。タイマーを手動で破棄することはお勧めしません。

于 2012-11-15T12:37:04.917 に答える