请问各位大佬,为什么TCP一个线程接收,一个线程处理,会出现队列为空的情况呢?

maoxiao181018 2020-07-15 10:40:05


private Queue queueTCPCacheReceived;
private Thread threadTCPCacheReceived;
static System.Threading.Timer Timer2 ;


private void ReceiveInformation2(Object state)//定时器用于接收数据
{
try
{
byte[] readBuffer = new byte[sock.ReceiveBufferSize];
int count = sock.Receive(readBuffer);
lock (queueTCPCacheReceived.SyncRoot)
{
for (int i = 0; i < count; i++)
{
queueTCPCacheReceived.Enqueue(readBuffer[i]);
}
}
}
catch (Exception ex)
{
string EM = ErrorMessage(ex);
timer1.Enabled = false;//UI停止更新
Timer2.Change(Timeout.Infinite, Timeout.Infinite);
sock.Close();
MessageBox.Show(EM, "错误");
return;
}
}
Timer2.Change(0, Timeout.Infinite);
}


private void ThreadTCPCacheReceivedFunction()
{
List<byte> listData = new List<byte>();
while (sock != null && sock.Connected)
{
int cacheLength = queueTCPCacheReceived.Count;
Console.WriteLine(cacheLength.ToString());
if (cacheLength > 0)
{
lock (queueTCPCacheReceived.SyncRoot)
{
for (int i = 0; i < cacheLength; i++)
{
if (listData.Count == 0)
{
if ((byte)queueTCPCacheReceived.Dequeue() == 0x55 && (byte)queueTCPCacheReceived.Dequeue() == 0x00)
{
listData.Add(0x55);
listData.Add(0x00);
}
}
else if (listData.Count > 0)
{
listData.Add((byte)queueTCPCacheReceived.Dequeue());
}

if (listData.Count == 896)
{
lock (queueTCPCacheReceived.SyncRoot)
{
byte[] byteData =listData.ToArray();
if (byteData[0] == 85 && byteData[895] == 238)//首尾验证
{
if (nlink_linktrack_anchor_frame0.unpackAnchorFrame0Data(byteData, byteData.Length))
{
ErrorCount = 0;
}
}
}
listData.Clear();
}
}
}
}
}
queueTCPCacheReceived.Clear();
}
...全文
1174 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
maoxiao181018 2020-07-16
  • 打赏
  • 举报
回复
你说的我一个字都听不懂,哈哈。
  • 打赏
  • 举报
回复
如果使用“队列”概念,那就说明你可能是使用上个世纪8、90年代的 unix 系统传统风格思路。

15年历史的 .net 最“沉重”的做法
var x = 准备处理对象;
ThreadPool.QueueUserWorkItem(h => 异步处理消息(x));
的做法,或者最近5、6年的 Task.Run(.....) 做法,都是更合适的 .net 的做法。因为 .net 内置有系统级的强大任务队列管理机制,处理了各种数据和控制问题,你不用,偏用很多年前基于底层编程的开源 java 上的一些代码代码,基于队列自己写一套 Pool 或者 Task 管理出来,丢了数据出错误很容易。
wanghui0380 2020-07-16
  • 打赏
  • 举报
回复
引用 6 楼 maoxiao181018 的回复:
[quote=引用 4 楼 wanghui0380 的回复:]我们现在选择pipeline管道处理,如果你net版本低,那我们建议使用 BlockingCollection ,这是建议 在来说你的代码。Dequeue是获取并移出。那么你移出了,他当然长度会变的
而且我发现如果在获取count之后,sleep一段时间,就不会出现这个现象了。但是延时增加了不少,不太满足我的需求。[/quote] 哎呀,你自己都说是所谓的定时器了,在你sleep过程里,你不能保证你那个定时器不加东西 int cacheLength = queueTCPCacheReceived.Count; Console.WriteLine(cacheLength.ToString()); if (cacheLength > 0) { lock (queueTCPCacheReceived.SyncRoot) 看见你锁的顺序了么,你又没锁他,只能说,你靠的不是逻辑,而是巧合,巧合的是你sleep的过程,定时器运行了,巧合的是,定时器不但运行了,而且他还真收到数据了
wanghui0380 2020-07-16
  • 打赏
  • 举报
回复
额。 初始为9对把 现在我移除一个,现在是8对吧 你固定循环9次,那么第9次当然是空的。 其实你自己都说了,cacheLength = queueTCPCacheReceived.Count 比实际的队列长度大,因为实际队列已经比你最早进来的时候小了
maoxiao181018 2020-07-16
  • 打赏
  • 举报
回复
引用 4 楼 wanghui0380 的回复:
我们现在选择pipeline管道处理,如果你net版本低,那我们建议使用 BlockingCollection ,这是建议 在来说你的代码。Dequeue是获取并移出。那么你移出了,他当然长度会变的
而且我发现如果在获取count之后,sleep一段时间,就不会出现这个现象了。但是延时增加了不少,不太满足我的需求。
maoxiao181018 2020-07-16
  • 打赏
  • 举报
回复
引用 4 楼 wanghui0380 的回复:
我们现在选择pipeline管道处理,如果你net版本低,那我们建议使用 BlockingCollection ,这是建议 在来说你的代码。Dequeue是获取并移出。那么你移出了,他当然长度会变的
但是我先获取它的长度,再一个个移出,应该是刚好的才对啊。
wanghui0380 2020-07-16
  • 打赏
  • 举报
回复
我们现在选择pipeline管道处理,如果你net版本低,那我们建议使用 BlockingCollection ,这是建议 在来说你的代码。Dequeue是获取并移出。那么你移出了,他当然长度会变的
maoxiao181018 2020-07-15
  • 打赏
  • 举报
回复
好像是cacheLength = queueTCPCacheReceived.Count比实际的队列长度大。
maoxiao181018 2020-07-15
  • 打赏
  • 举报
回复
引用 1 楼 tangyanzhi1111 的回复:
你接收的时候,处理还没返回,所以...
没有返回吧。
江湖评谈 2020-07-15
  • 打赏
  • 举报
回复
你接收的时候,处理还没返回,所以...

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧