I have a service which talks to around 50 devices over Ethernet using TCP. These devices push data at various speeds (ranging from 50ms to 1500ms). Hence I use BlockingCollection (per device) for queuing the received data and then processing the data in a different thread.
To consume and process the data from the BlockingCollection, I used an explicit thread per device as shown below
private void ThreadProc(object o)
{
while (true)
{
DeviceData data = m_blockingCollection.Take();
ProcessData(data);
}
}
IMHO, this is a simple and elegant solution since these threads will be blocked if there is no data available and will not consume CPU.
One alternate approach (recommended by colleagues) is a timer with an interval of 250ms. But I have a gut feeling that scheduling around 50 operations every 250 milliseconds might be costlier. For faster devices this will slow down processing and for slower devices this will cause unnecessary execution of the timer logic.
private void OnTimeOut(object o)
{
if (m_blockingCollection.TryTake(out DeviceData data))
{
ProcessData(data);
}
}
On researching about this, I also found about ThreadPool.RegisterWaitForSingleObject which looks apt to the problem. Hence I modified the code as below
AutoResetEvent m_dataEvent = new AutoResetEvent(false);
RegisteredWaitHandle reg = ThreadPool.RegisterWaitForSingleObject
(m_dataEvent, ConsumeAndProcess, null, -1, false);
private void OnDeviceDataRecevied(DeviceData data)
{
sm_blockingCollection.Add(data);
m_dataEvent.Set();
}
private static void ConsumeAndProcess(object state, bool timedOut)
{
if (sm_blockingCollection.TryTake(out int data))
{
ProcessData(data);
}
}
Did I think correctly? Is the 3rd approach better than the first and second? Which will be better in terms of efficiency and in terms of less resource usage?