我试图在屏幕上显示来自ssl流(来自网站)的任何数据。因为我不知道数据何时到达,所以我使用了另一个线程,它一直从流中读取数据直到字节被读取。这是完美的工作,然而,我的CPU使用率跳转到25%,并停留在那里(这是一个线程的最大使用,我的PC有4个线程)。虽然这有点道理,因为线程被困在when循环中,但我没想到thread类的实例会占用整个CPU线程(我敢肯定,在使用简单的Client/Server应用程序时没有发生这种情况)。
当连接初始化后,线程就开始运行,用户可以随时向网站发送数据,应用程序应该打印响应。什么是解决这一问题的替代办法?我应该放弃SslStream并开始使用其他的东西吗?
下面是运行在这个单独线程上的代码:
void ReadDataAsync(Object obj) {
byte[] buffer = new byte[65536]; //65536, make sure all bytes can be
//from a single packet
int bytesRead = -1;
while (true) {
//It makes sense for sslStream.Read to block until bytes have been
//read, but it doesn't. Which is why I'm checking if bytesRead!=0
bytesRead = sslStream.Read(buffer, 0, 65536);
if (bytesRead != 0) {
Console.WriteLine(Encoding.UTF8.GetString(buffer, 0, bytesRead));
buffer = new byte[65536];
}
}
}谢谢大家,感谢你们的帮助
编辑:
按照"gt“的建议,我尝试使用BeginRead和EndRead。为此,每当用户发送请求时,我都使用BeginRead。当收到所有的数据后,我就把它们打印在屏幕上。这似乎很好,但我担心将来是否会有任何问题。这些包裹有可能被搞砸了吗?例如,是否有可能EndRead在第一个数据包的末尾不返回0,并且继续读取第二个数据包?如果可能的话,我该怎么继续解决这个问题呢?接收到的数据只是http层的主体,所以我不能事先访问IP层来知道数据包的长度。
public void SendData(byte[] message) {
sslStream.Write(message);
sslStream.Flush();
//Start reading for response (if not already reading)
if (sslStream.CanRead) {
sslStream.BeginRead(buffer, 0, BufferSize, ReadData, null);
}
}
void ReadData(IAsyncResult ar) {
int bytesRead = sslStream.EndRead(ar);
if (bytesRead > 0) {
//data may be on their way so start reading again
message.Append(Encoding.UTF8.GetString(buffer, 0, bytesRead));
sslStream.BeginRead(buffer, 0, BufferSize, ReadData, null);
Console.WriteLine("Data received but more may be on their way...");
} else {
//All data arrived (Checking if length is more than 0 since all the
//data may had already arrived in the previous check (above)
if (message.ToString().Length > 0) {
Console.WriteLine(message.ToString());
//Clear StringBuilder and reset buffer.
message.Clear();
buffer = new byte[BufferSize];
}
}
}再次感谢
发布于 2013-03-25 14:57:22
看到while(true)通常是个坏兆头..。如果您的代码在没有结束条件的情况下进入“紧密”循环,它将继续循环并消耗它的所有可用资源。
再次检查“if”条件是否符合您的预期。例如,如果流在多个部分中读取,会发生什么情况?(例如32768的两部分)。这是完全可能的。
一旦您对这种行为感到满意,就可以强制线程在尝试下一个Read之前先休眠一段时间,使用Thread.Sleep(100)。
或者,尝试使用BeginRead查看异步IO。见在MSDN上的示例。
编辑,以回答问题的第2部分:
我怀疑如果某件事可能出错,它就会出错,所以代码是防御性的!下一个问题的解决方案是缓冲从流中读取的所有数据。然后让另一个线程尝试从缓冲区读取整个数据包。不要忘记使用锁来防止同时读取/写入缓冲区。
为此编写单元测试也是个好主意,以涵盖“零散”行为(以及正常行为)。
或者,您可以查看更高级别的协议,该协议为您处理这些问题。我经常提到的一个例子是谷歌的协议缓冲器。
https://stackoverflow.com/questions/15617256
复制相似问题