3
我試圖實現一個類,它使用一個簡單的緩存來保存從內部服務檢索到的數據。我使用ManualResetEvent來阻塞多個線程,這些線程可能會嘗試在第一個線程同時刷新緩存的數據,以通過調用Set(),然後調用Reset()來成功地通知其他人繼續進行數據檢索。在測試時我注意到有時候所有的線程都被釋放了,有時候有一個或者更多的線程不會被超時,就好像我在所有的線程被釋放之前調用Reset一樣。有人能解釋我做錯了什麼嗎?ManualResetEvent問題不會一直釋放所有等待的線程
我已經包含下面的代碼的減少版本。
private bool _updating;
private const int WaitTimeout = 20000;
private DateTime _lastRefresh;
private object _cacheData;
private readonly ManualResetEvent _signaller = new ManualResetEvent(false);
private void RefreshCachedData()
{
Console.WriteLine("ThreadId {0}: Refreshing Cache", Thread.CurrentThread.ManagedThreadId);
if (_updating)
{
Console.WriteLine("ThreadId {0}: Cache Refresh in progress, waiting on signal.", Thread.CurrentThread.ManagedThreadId);
// another thread is currently updating the cache so wait for a signal to continue
if (!_signaller.WaitOne(WaitTimeout))
Console.WriteLine("ThreadId {0}: Thread timed out ({1}s) waiting for a signal that the cache had been refreshed",
Thread.CurrentThread.ManagedThreadId,WaitTimeout);
Console.WriteLine("ThreadId {0}: Signal recieved to use refreshed cache.", Thread.CurrentThread.ManagedThreadId);
}
else
{
try
{
_updating = true;
var result = _requestHandler.GetNewData();
if (!result.Success)
{
Console.WriteLine("Failed to retrieve new data.");
}
else
{
// switch the cache with the new data
_cacheData = result.Data;
Console.WriteLine(
"ThreadId {0}: Cache refresh success.",
Thread.CurrentThread.ManagedThreadId);
Thread.Sleep(8000);
}
}
catch (Exception ex)
{
Console.WriteLine("Error occured: {0}", ex);
}
finally
{
// Set the refresh date time regardless of whether we succeded or not
_lastRefresh = DateTime.Now;
_updating = false;
// signal any other threads to to carry on and use the refreshed cache
Console.WriteLine("ThreadId {0}: Signalling other threads that cache is refreshed.", Thread.CurrentThread.ManagedThreadId);
_signaller.Set();
_signaller.Reset();
}
}
}
'的Thread.Sleep(8000) '和'WaitOne'聽起來好像不會很好地播放。 – leppie 2012-07-25 09:27:04
線程睡眠只是爲了測試的目的,以確保所有其他線程進入等待線程刷新緩存釋放他們之前 – gouldos 2012-07-25 09:30:26
這可能是一個紅色的鯡魚,但如果我把一個線程睡眠50ms之間的集並重置,我還沒有看到在測試任何線程不會被釋放。 – gouldos 2012-07-25 09:50:19