데이터를 지속적으로 처리하는 서비스가 있고 메시징을 통해 새 데이터를 처리하라는 요청을받습니다. 처리량이 많으면 새로운 요청이 병합되어 한꺼번에 처리됩니다. AutoResetEvent는 새 요청을 사용할 수 있음을 프로세서에 알리는 데 사용됩니다.AutoResetEvent를 사용하여 작업자 스레드에 신호 보내기
WaitOne 이후 currentRequest가 null이 될 수 있으면 제 질문은 EventLoop에 있습니까?
_eventAvailable.Set()을 잠금 (_eventLocker) 외부에 두는 것은 나쁜 습관입니까? WaitOne에서 시작하지 않고 즉시 잠금 장치 (_eventLocker)에 컨테스트를하지 않도록 이동했습니다.
다음 코드를 더 잘 작성하는 방법에 대한 제안 사항이 있으십니까?
public sealed class RealtimeRunner : MarshalByRefObject
{
/// <summary>
/// The actual event, new events get merged into this if it is not null
/// </summary>
private Request _pendingRequest;
/// <summary>
/// Used to signal the runner thread when an event is available to process
/// </summary>
private readonly AutoResetEvent _eventAvailable = new AutoResetEvent(false);
private readonly object _eventLocker = new object();
/// <summary>
/// Called on a background thread via messaging
/// </summary>
public void QueueEvent(RealtimeProcessorMessage newRequest)
{
bool mergedRequest;
lock (_eventLocker)
{
if (_pendingRequest == null)
{
mergedRequest = false;
_pendingRequest = new Request(newRequest, _engine);
}
else
{
mergedRequest = true;
_pendingRequest.Merge(newRequest, _engine);
}
}
_eventAvailable.Set();
}
/// <summary>
/// This is running on its own thread
/// </summary>
private void EventLoop()
{
while (true)
{
// Block until something exists in _pendingRequest
_eventAvailable.WaitOne();
Request currentRequest;
lock (_eventLocker)
{
currentRequest = _pendingRequest;
_pendingRequest = null;
}
// CAN THIS EVER BE NULL?
if (currentRequest == null)
continue;
//do stuff with the currentRequest here
}
}
}
감사합니다. 제작자 소비자를 살펴 봤지만 여러 요청을 단일 요청으로 병합 할 수 있기 때문에 좀 더 수동적 인 접근 방법을 원했습니다. 내 서비스 처리에는 30 초가 걸릴 수 있으며 요청은 초당 여러 번 올 수 있습니다. TryTake를 반복 사용하여 소비자 측에서 이들을 병합 할 수 있다고 생각하십니까? 그래서 하나의 m_Queue.Take() 호출이있을 것입니다 (m_Queue.TryTake())? – BrandonAGr
@BrandonAGr : 물론입니다. 'Take '를 호출하여 초기 요청을 얻은 직후에'TryTake'를 호출하는 또 다른 루프를 돌면서 몇 가지 요청을 신속하게 선택할 수 있습니다. 여기에는 많은 가능성이 있습니다. 그러나 대기열이 비어있을 때 블로킹 효과를 발생 시키려면 여전히 'Take'를 호출해야합니다. –