2017-09-28 4 views
0

私はいくつかのタイムアウト期間が満了しているかどうかをチェックする方法があり、それが持っている場合は、開始時間をリセットし、trueを返します:タイムアウトを原子的にチェックしてリセットするにはどうすればよいですか?

bool CheckAndResetTimeout() { 
    if (DateTime.UtcNow > _start + _timeout) { 
     _start = DateTime.UtcNow; 
     return true; 
    } 
    return false; 
} 

私はもし2つのスレッドがヒットするという意味で、このスレッドを安全にするにはどうすればよいですそれは同時に、一度だけ真実を返すことが保証されていますか?私はこれがダブルチェックロッキングによって達成できると思いますが、私はBCL(これはおそらくSystem.Threadingの下にあります)の中で、より高いレベルの抽象化を提供するものを見つけることを望んでいました。私は、可能な場合、そのようなSysetm.Threading.Interlockedから軽量構造物を構成することなどによって、lockを避けることを望んだが、私は持っていない

static object TimerLock = new object(); 
static bool CheckAndResetTimeout() 
{ 
    lock (TimerLock) 
    { 
     if (DateTime.UtcNow > _start + _timeout) 
     { 
      _start = DateTime.UtcNow; 
      return true; 
     } 
     return false; 
    } 
} 

https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement

+0

なぜ実際のタイマーを使用しないのですか?それはあなたのために内部的にこれを扱うでしょう - あなたはインターバルが経過するときにコールバックを得るでしょう。 – xxbbcc

+0

https://msdn.microsoft.com/en-us/library/system.threading.timer(v=vs.110).aspx – xxbbcc

+0

私はそれが怠け者になりたいので。タイムアウトが切れた場合、それを呼び出すことは何らかの作業を行う責任があり、その作業をより頻繁に行う必要はありません。 –

答えて

1

3

あなたはこのためにlockキーワードを使用することができますそうするための良い方法を思いついてください。今のところ私はdouble-checked lockingをやっています。少なくともlockのオーバーヘッドを避けてください。です。

private readonly object _timeoutLock = new object(); 

public bool CheckAndResetTimeout() { 
    if (DateTime.UtcNow > _start + _timeout) { 
     lock (_timeoutLock) { 
      if (DateTime.UtcNow > _start + _timeout) { 
       _start = DateTime.UtcNow; 
       return true; 
      } 
     } 
    } 
    return false; 
} 
+0

私は、できるだけ軽量な 'Sysetm.Threading.Interlocked'からコンストラクトを作成するなど、できるだけ'ロック 'を避けることを望んでいました。私はそれを行う方法を考え出していない。 –

+0

私が自分のものよりも良い答えを望んでいたのと同じように、それは私が行った解決策であり、二重チェックはロックオーバーヘッドを避けることに大きな違いを生むので、受け入れたとマークしました。ロックを提案してくれたあなたに+1しても、実際にはロックを使用していたので、公正であるようです。 :) –

関連する問題