线程无限循环中 CPU 使用率增加至 100%
我正在 ASP.NET Web 应用程序中实现一个基于 Web 的聊天平台,并且使用类似于长轮询的技术。我的意思是我将来自客户端的每个网络请求保留特定的时间段(超时)或直到新消息到达,然后将响应发送到客户端。
我将连接的客户端保留在内存中(字典对象),并且每当有新消息发送到客户端时,我都会将此消息写入接收方客户端的消息数组中。 客户端需要发送一个请求来获取自己的消息,我将这个请求保存在内存中的一个数组中。
我正在使用异步 http 处理程序来侦听客户端请求,我将 Web 请求保存在内存中的数组中。我使用线程从内存中连续检查新消息(在为每个客户端创建的字典中)。
我不使用 .net 线程池线程来检查新消息或超时的 Web 请求。我创建如下线程:
System.Threading.Thread t = new Thread(new ThreadStart(QueueCometWaitRequest_WaitCallback));
t.IsBackground = false;
t.Start();
在每个线程的 QueueCometWaitRequest_WaitCallback 方法中,我处于无限 while 循环中:
while (true)
{
...
Thread.Sleep(100);
}
在该方法中,我正在检查 Web 请求时间每个 Web 请求的输出或新消息也保存在内存中的数组中。
一切都运行良好,直到我注意到 CPU 使用率及时达到 100%。 (在第一个连接客户端后的几分钟内) 在第一个请求开始时,一切似乎都很正常,我的意思是,在向客户端返回响应时,CPU 使用率不高于 10%。但即使有 2 个客户端,CPU 使用率最终也会增加到 100%。似乎只有在写入客户端请求的响应时,CPU 使用率才是 100%。如果没有客户端离开,那么一切都会恢复正常(CPU 使用率约为 0%),直到客户端完成新的 Web 请求。
我不详细了解线程,但我对我创建并无限工作的新线程表示怀疑。这就像操作系统及时为它们提供了更多的 CPU 使用率和资源,因为它们一直在工作,而这个 Thread.Sleep(100) 不起作用。
这是 QueueCometWaitRequest_WaitCallback() 方法:
void QueueCometWaitRequest_WaitCallback()
{
while (true)
{
if (processRequest.Length == 0)
{
Thread.Sleep(100);
}
else
{
for (int i = 0; i < processRequest.Length; i++)
{
Thread.Sleep(100);
// below I am checking for new message or request time out
.................
.................
// If new message or time out I write to response
}
}
}
}
我希望我能解释一下情况,并且我也愿意接受任何建议(例如以不同的方式实现)
如果您能帮助我解决这个问题,我将不胜感激, 谢谢
I am implementing a web based chat platform in ASP.NET Web Application, and I use technique similar to long polling. I mean I keep each web request from client for a specific time period(timeout) or until new message arrives, and then response is sent to the client.
I keep connected clients in memory(dictionary object) and when ever new message is sent to a client, I write this message into receiver client's messages array.
Client needs to send a request to get his own messages, and I keep this request in an array in memory.
I am using asynchronous http handler for listenings client request, I am keeping web requests in an array in memory. I use threads to check for new messages continously from memory (in dictionary which is created for each client).
I do not use .net thread pool threads to check for new messages or timed out web requests.I create threads like this:
System.Threading.Thread t = new Thread(new ThreadStart(QueueCometWaitRequest_WaitCallback));
t.IsBackground = false;
t.Start();
In each thread's QueueCometWaitRequest_WaitCallback method I am in an infinite while loop:
while (true)
{
...
Thread.Sleep(100);
}
In this method, I am checking for web request time out or new message for each Web Request which is also kept in an array in memory.
Everything was working good until I noticed that CPU usage is reaching up to 100% in time. (in minutes after the first connected client)
At the beginning of first request everything seems to be normal, I mean the CPU usage is not higher than 10% while returning a response to the client. But in time even with 2 clients the CPU usage is increasing up to 100%. It seems CPU usage is 100% only when writing to a response for a client request. If no client is left then everything return to a normal (CPU usage is about 0%) until new web request is done by a client.
I don't know the threads in detail, but I am suspicious about the new threads which I created and works infinitely. It is like operating system gives them more CPU usage and resource in time since they are working all the time, and this Thread.Sleep(100) is not working.
Here is the QueueCometWaitRequest_WaitCallback() method:
void QueueCometWaitRequest_WaitCallback()
{
while (true)
{
if (processRequest.Length == 0)
{
Thread.Sleep(100);
}
else
{
for (int i = 0; i < processRequest.Length; i++)
{
Thread.Sleep(100);
// below I am checking for new message or request time out
.................
.................
// If new message or time out I write to response
}
}
}
}
I hope I could explain the situation, and I am open to any suggestion as well (like implementing in a different way)
If you can help me with this problem I will appreciate gratefully,
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
就像一般的最佳实践评论而不是直接答案一样 - 不建议在消息接收器线程内编写 Thread.Sleep(100) 。更好的方法是使用前面提到的 Thread.Join 或 ManualResetEvent 等待句柄。例如,您可以这样编写代码:
这将确保您的线程在等待时使用 0% CPU,并且仅在有工作要做时才消耗 CPU。
如果做不到这一点,您是否考虑过异步双向消息传递的第三方解决方案?我在 .NET 应用程序中使用 RabbitMQ (AMQP) 来处理高吞吐量消息传递,并取得了巨大成功。 RabbitMQ 的 API 意味着当收到消息时您会收到一个事件,然后可以在后台线程上处理该消息。
此致,
Just as a general best-practices comment as opposed to direct answer - it's not advisbable to write a Thread.Sleep(100) inside your message receiver thread. A better method would be to use Thread.Join as previously mentioned or ManualResetEvent wait handles. For instance, you could code like this:
This would ensure that your thread uses 0% CPU while waiting and only consumes CPU when there is work to do.
Failing that have you thought about a third party solution to asynchronous bi-directional messaging? I have used RabbitMQ (AMQP) with great success in .NET applications to handle high throughput messaging. The API for RabbitMQ means you get an event back when a message has been received which can then be processed on a background thread.
Best regards,
如果静态使用,字典对象不是线程安全的。如果将其用作静态成员,则需要创建一个 Lock 语句。
下面是从 Log4Net LoggerFactory 类中提取的示例...请注意,TypeToLoggerMap 是一个字典对象,当通过 GetLogger 方法引用它时,将使用 Lock 语句。
查看这篇文章 - 这是我发现上述有关 Dictionary 对象的信息的地方。
https://www.toptal.com/dot -net/hunting-high-cpu-usage-in-dot-net
作为旁注,您是否考虑过在您的项目中使用 SignalR?
Dictionary objects aren't thread safe if used statically. If using it as a static member then you need to create a Lock statement.
Here's an example lifted from a Log4Net LoggerFactory class...Notice that the TypeToLoggerMap is a dictionary object and when it's referenced vai the GetLogger method, a Lock statement is used.
Check this article out - this is where I discovered the above info about Dictionary objects.
https://www.toptal.com/dot-net/hunting-high-cpu-usage-in-dot-net
As a side note, have you considered using SignalR for your project?