我的连接处理程序在下面(这更多是为了个人实验而不是生产代码)
如果我不在 while 循环的任何地方添加 Thread.Sleep,它就会开始消耗 CPU。相反,如果我做 Sleep 来缓解无休止的 while-spam,我会错过断开连接的机会。CPU 会上升与正在运行的客户端/线程的数量成正比,因此导致高使用率的不是监听器本身,而是下面发布的实际客户端线程。任何人对如何解决这个问题有任何想法吗?
(我正在避免基于 await 的解决方案,因为我对 async/await 不够熟悉,线程方法对于这个相当小的项目工作正常)
我只是简单地搜索了 SO 以寻找解决方案,但没有注意到任何这个特定问题或提供了除了指导人们阅读异步/等待文章之外的解决方案,如果我确实错过了适用的答案,我深表歉意。
private void HandleConnection(CancellationToken ct) {
int recv = 0;
byte[] buf = new byte[4096];
Trace.WriteLine($"{_name} Connected");
if (_ns.CanWrite && _client.Connected) {
_ns.Write(Encoding.BigEndianUnicode.GetBytes("■WEL"), 0, Encoding.BigEndianUnicode.GetBytes("■WEL").Length);
try {
while (_client.Connected && !ct.IsCancellationRequested) {
while (!_ns.DataAvailable) { //first attempted solution
Thread.Sleep(100); // miss discon if i sleep here
}
if (ct.IsCancellationRequested) {
Trace.WriteLine($"{(string)this} thread aborting");
break;
}
buf = new byte[4096];
if (_client.Connected && _ns.DataAvailable) {
recv = _ns.Read(buf, 0, buf.Length);
} else {
recv = 0;
}
if (recv > 0) {
string r = Encoding.BigEndianUnicode.GetString(buf);
r = r.TrimEnd('\0');
if (String.IsNullOrEmpty(r) || String.IsNullOrWhiteSpace(r))
r = null; //need the !not version
else
if (ParseMsg(r))
break;
}
//Thread.Sleep(100); // also miss discon here too
}
} catch (IOException ioe) { }
Trace.WriteLine($"{_name} Disconnected");
if (OnDisconnected != null)
OnDisconnected(this);
}
}
最佳答案
通过套接字进行通信的正确方法是:
- 持续阅读。这些读取将阻塞,直到数据进入或直到套接字正常断开连接(可通过读取 0 字节完成的读取检测到)。
- 定期写作。 These writes are required to ensure the connection is still viable .
正确的线程方法要求每个连接两个线程。我不相信它比异步方法更简单。
附言如果您的代码使用 Connected
,那么它就有一个错误。正确的解决方案永远不需要使用 Connected
。
关于C# 监听器线程上的 CPU 使用率高,休眠未命中断开连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43327534/