내부 서비스에서 검색 한 데이터를 보유하기 위해 간단한 캐시를 사용하는 클래스를 구현하려고합니다. 첫 번째 스레드가 Set() 및 Reset() 호출하여 데이터를 검색 한 다른 진행 신호를 성공하려면 동시에 캐시 된 데이터를 새로 고치려면 시도 할 수있는 여러 스레드를 차단하려면 ManualResetEvent 사용하고 있습니다. 테스트 할 때 때로는 모든 스레드가 해제되고 때로는 1 개 이상이 해제되고 모든 스레드가 해제되기 전에 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
스레드 수면은 스레드가 캐시를 새로 고치기 전에 다른 모든 스레드가 대기 상태가되었는지 확인하기 위해 테스트를 목적으로 만있었습니다. – gouldos
이것은 빨간색 청어가 될 수 있지만 세트 사이에 50ms의 스레드 수면을 넣으면 재설정하고 나면 아직 릴리스되지 않은 모든 스레드를 테스트 해보아야합니다. – gouldos