【问题标题】:best practice for using an infinite while loop to process client/server data [closed]使用无限while循环处理客户端/服务器数据的最佳实践[关闭]
【发布时间】:2015-05-17 19:42:11
【问题描述】:

我正在开发一个客户端 - 服务器应用程序。而且我有一个无限的while循环来检查客户端(或服务器)是否已发送数据。

while (true)
{
    // do things
}

但是,最好的做法是什么?使用上面的代码,当服务器接受一个客户端时,系统的 CPU 会跳到 100%。

如果我将Threading.Thread.Sleep(500) 放在循环的末尾,CPU 使用率会更好,但我想知道这是否是最好的方式,或者是否应该有所不同。

(我知道,我能够异步获取数据——但我的问题不在于,这是关于 while 循环的最佳实践,以便应用程序不会完全消耗 CPU)

【问题讨论】:

  • 好吧,IMO 这里的最佳做法是使用异步读取(或者如果您不想这样做,更小睡眠 - 比如 10 毫秒)
  • 这绝对是无限 while 循环的最佳实践(在大多数情况下预计会占用 100% 的 CPU)。如果您对网络实践有疑问 - 异步代码是更好的方法。
  • @Cageman 我不确定删除NetworkStream 相关的东西是个好主意。至少它显示了您正在使用的内容,而(没有双关语)带有空 try-catchwhile 循环似乎与您的客户端-服务器问题仅略微相关,并且没有说明您使用的技术。无论如何,正如 Alexei 已经指出的那样,async networking 是使用网络 IO 操作的正确方式。
  • @Ahmedilyas 如果一个简单的侦听程序/服务耗尽了他机器的完整核心,你的管理员可能会有点不高兴......只是说;)
  • @Cageman 在这种情况下唯一的答案是,在一般情况下,您应该 根本不使用while (true) {...}

标签: c# while-loop


【解决方案1】:

我想知道这是否是最好的方法

没有。

没有转义机制的无限循环(breakyield return)(几乎)不是一个好主意。

或者说应该不一样

是的。

您正在执行“忙等待”循环,等待客户端发送数据。所以你的循环应该是 I/O 绑定的,而不是重复轮询的 CPU 绑定。这在 cmets 中已经多次提及。

但是为了论证的目的,我们假设

  • 您的代码实际上受 CPU 限制,
  • 定期需要“轮询”某些条件才能做某事,
  • 您不能使用标准同步或信号原语(如阻塞队列、事件、信号量...)“等待”或“等待”该条件。

那么任何解决方案至少需要处理两个部分:

  1. 循环的停止条件。
  2. 仅在实际需要时才消耗 CPU 并占用线程。

停止条件

执行此操作的一种方法是使用连接到CancellationTokenSourceCancellationToken 以实现干净的停止方式。

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 不同的计时器
  • 根据需要动态调整计时器间隔。

【讨论】:

  • 优秀的答案,几乎是我在 OP 下的 cmets 中的目标:)
  • @Alex 谢谢,我认为这正是我要找的,赞成你的回答,但没有准备好回答。今晚我将对给出的答案进行一些研究。
【解决方案2】:

您听说过BackgroundWorker 组件吗? 这对您的情况很有用。

【讨论】:

    猜你喜欢
    • 2013-02-25
    • 2015-08-11
    • 2020-08-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 1970-01-01
    • 2020-11-11
    相关资源
    最近更新 更多