1
請注意以下幾點:以下示例使用Interlocked.CompareExchange是否需要揮發性和/或內存障礙?
private DateTime m_lastTimeUtc;
private int m_isInProgress;
...
if (DateTime.UtcNow - m_lastTimeUtc >= m_interval)
{
if (Interlocked.CompareExchange(ref m_isInProgress, 1, 0) == 0)
{
if (DateTime.UtcNow - m_lastTimeUtc >= m_interval)
{
m_lastTimeUtc = DateTime.UtcNow;
// Do the work
m_lastTimeUtc = DateTime.UtcNow;
Interlocked.Exchange(ref m_isInProgress, 0);
}
}
}
這段代碼的目的語義如下:
- 該代碼可以經常被引用 - 數百次。
- 它應該或多或少地定期做某些工作。如果代碼沒有經常被調用,那麼實際的時間可能非常不規則,這是可以的。但如果它經常被調用(通常是這種情況),那麼這項工作就會經常進行。
- 碰到
m_isInProgress = 1
的線程將跳過工作,它是完全沒問題的。
當然,環境是多線程的。
我注意到人們正在使用的關鍵字volatile
和/或調用Interlocked.MemoryBarrier()
做的事情類似,我在這裏做什麼的時候(或者至少看起來是這樣給我)。如果我知道我理解他們兩人是如何工作的,我會說謊。
有人可以解釋我是否需要他們在我的代碼,爲什麼?
P.S.
我有幾個地方重複相同的模式。所以,我要爲大家介紹以下方法:
private static void DoWork(TimeSpan interval, ref DateTime lastTimeUtc, ref int isInProgress, Action work)
{
if (DateTime.UtcNow - lastTimeUtc >= interval && Interlocked.CompareExchange(ref isInProgress, 1, 0) == 0 && DateTime.UtcNow - lastTimeUtc >= interval)
{
lastTimeUtc = DateTime.UtcNow;
work();
lastTimeUtc = DateTime.UtcNow;
Interlocked.Exchange(ref isInProgress, 0);
}
}
鑑於這種方法,這是我想讓它被調用:
DoWork(m_interval, ref m_lastTimeUtc, ref m_isInProgress,() =>
{
// Do the work
});
請問答案是一樣的DoWork
?
謝謝,我一定會看你的建議的文章。 – mark