处理在不同线程中读取的TCP套接字数据



我正在开发一个程序,与每70毫秒通过TCP信道发送数据的设备集成。

我正在使用Socket。BeginReceive和Socket。EndReceive方法读取数据。逻辑如以下伪代码所示

private void OnReceived(IAsyncResult ar)
{
var rcvdDataLength = m_tcpSocket.EndReceive(ar);
Array.Copy(m_tempRecvBuffer, 0, m_mainBuffer, m_mainBufferDataIndex, rcvdDataLength);
if (CheckIfValidHeaderAndBodyReceived())
{
var actualData = new byte[headerLen + BodyLen];
Array.Copy(m_mainBuffer, m_dataIndex, actualData, 0, headerLen + BodyLen);
Process(actualData);
}
m_tcpSocket.BeginReceive(m_tempRecvBuffer, 0, m_tempRecvBuffer.Length, SocketFlags.None,
OnReceived, null);
}

上面代码中描述的流程功能负责实现业务逻辑。处理功能目前大约需要300毫秒。

因此,消费者(花费300毫秒(比生产者(每70毫秒发布一次数据(慢。我是否需要异步运行此Process函数以避免延迟?还是TCP层的流量控制方面负责这个?

是否需要异步运行此Process函数以避免延迟?

这取决于您的应用程序,最终取决于您自己的优先级决定。严格地说,不,你不需要异步地做任何事情,但这可能是一件好事。

我通常使用并推荐的方法是一个专用于接口的线程,该线程通过队列与应用程序的其余部分交互。当通信线程接收消息时,它会锁定一个队列并将其推入。当主应用程序准备好使用这些数据时,它就会根据需要锁定该队列并退出队列。这是一种简单、稳健且可靠的机制。转到您的伪代码:

private void OnReceived(IAsyncResult ar)
{
var rcvdDataLength = m_tcpSocket.EndReceive(ar);
Array.Copy(m_tempRecvBuffer, 0, m_mainBuffer, m_mainBufferDataIndex, rcvdDataLength);
if (CheckIfValidHeaderAndBodyReceived())
{
var actualData = new byte[headerLen + BodyLen];
Array.Copy(m_mainBuffer, m_dataIndex, actualData, 0, headerLen + BodyLen);
lock(messageQueue)
{
messageQueue.Enqueue(actualData);
}
}
m_tcpSocket.BeginReceive(m_tempRecvBuffer, 0, m_tempRecvBuffer.Length, SocketFlags.None,
OnReceived, null);
}

然后在你的应用程序中:

void ProcessQueue()
{
Queue<byte[]> tempQueue = new Queue<byte[]>();
lock(messageQueue)
{
// Drain the queue so we can release the lock ASAP
while(messageQueue.Count > 0)
{
tempQueue.Enqueue(messageQueue.Dequeue());
}
}
while(tempQueue.Count > 0)
{
Process(tempQueue.Dequeue());
}
}

最新更新