我正在开发客户端-服务器应用程序。而且我有一个无限的 while 循环来检查客户端(或服务器)是否已发送数据。
while (true)
{
// do things
}
但是最好的做法是什么?通过上面的代码,当服务端接受一个客户端时,系统的CPU会跳到100%。
如果我将 Threading.Thread.Sleep(500)
放在循环的末尾,CPU 使用率会更好,但我想知道这是否是最好的方法,或者它是否应该有所不同。
(我知道我可以异步获取数据——但我的问题不是这个,它是关于 while 循环的最佳实践,这样应用程序就不会完全消耗 CPU)
I wonder whether this is the best way
没有。
没有转义机制(break
、yield return
)的无限循环(几乎)永远不是一个好主意。
or that it should be different
是的。
您正在进行“忙等待”循环,等待客户端发送数据。所以你的循环应该是 I/O 绑定(bind)的,而不是通过重复轮询来绑定(bind) CPU 的。这一点已经在评论中多次提及。
但是为了论证我们假设
- 您的代码实际上受 CPU 限制,
- 您定期需要“轮询”某些条件才能做某事,
- 您不能使用标准同步或信号原语(如阻塞队列、事件、信号量...)“等待”或“等待”该条件。
那么任何解决方案都至少需要处理两个部分:
- 循环的停止条件。
- 仅在实际需要时才消耗 CPU 并占用一个线程。
停止条件
执行此操作的一种方法是使用连接到 CancellationTokenSource
的 CancellationToken
以允许干净的停止方式。
while (!cancelToken.IsCancellationRequested)
{
// Do stuff
// Note: this still does not solve the issue of eating CPU resources.
// If you were not polling periodically but waiting for a condition,
// you could now do:
try
{
var someResult = await MyCancelableAsyncOperation(..., cancelToken);
// do stuff with this result.
}
catch (OperationCanceledException)
{
break; // done
}
}
定期轮询
如果您需要定期执行操作,请使用可取消计时器。
请在此处查看示例:https://stackoverflow.com/a/30225642/2573395
请注意,此示例说明了基本思想。可以修改为:
- 使用不同于
System.Timers.Timer
的定时器
- 根据需要动态调整计时器间隔。