没有 while(true) 循环的 C# 非阻塞套接字

Posted

技术标签:

【中文标题】没有 while(true) 循环的 C# 非阻塞套接字【英文标题】:C# non-blocking socket without while(true) loop 【发布时间】:2010-12-12 13:20:34 【问题描述】:

我只是想进行一些套接字编程,在 c# 中使用非阻塞套接字。 我发现的各种样本,例如this,似乎使用了一个while(true) 循环,但这种方法会导致cpu 以100% 的速度爆裂。 有没有办法使用事件编程风格使用非阻塞套接字? 谢谢

【问题讨论】:

【参考方案1】:

一般来说阻塞/非阻塞IO,普遍适用:

关键在于,在现实生活中,您的程序会做其他事情而不做 IO。例子都是这样设计的。

在阻塞 IO 中,您的线程在等待 IO 时会“阻塞”。操作系统会去做其他事情,例如允许其他线程运行。因此,您的应用程序可以通过使用多个线程并行执行许多事情(从概念上讲)。

在非阻塞 IO 中,您的线程会查询是否可以进行 IO,否则会执行其他操作。因此,您可以通过在应用程序级别显式地在它们之间进行交换来并行执行许多事情。

【讨论】:

这个答案给出了一些关于为什么要进行非阻塞 IO 的理论,但并没有真正回答发布者关于如何实现它的问题。【参考方案2】:

Socket.BeginReceive 和 AsyncCallback

【讨论】:

【参考方案3】:

请参阅 MSDN 示例 here。该示例显示了如何异步接收数据。您还可以使用 Socket BeginSend/EndSend 方法异步发送数据。

您应该注意,回调委托在 ThreadPool 线程的上下文中执行。如果在回调中接收到的数据需要与另一个线程共享,这很重要,例如,在 Windows 窗体中显示数据的主 UI 线程。如果是这样,您将需要使用 lock 关键字同步访问数据。

正如您所注意到的,使用非阻塞套接字和 while 循环,处理器被固定在 100%。异步模型只有在有数据发送或接收时才会调用回调委托。

【讨论】:

【参考方案4】:

为避免在繁重的 while 循环中出现 CPU 问题,当没有数据接收时,将 thread.sleep(100) 或更少。这将让其他进程更改以完成他们的任务

【讨论】:

以上是关于没有 while(true) 循环的 C# 非阻塞套接字的主要内容,如果未能解决你的问题,请参考以下文章

在多线程应用程序表单上使用while循环锁定c#阻塞单核机器上的所有线程

socket执行accept函数时没有进入阻塞状态,而是陷入了无限循环

非阻塞套接字与IO多路复用

非阻塞标准输出[C/Linux]

非阻塞控制台输入?

While 循环计时如何在带有多个线程的 C# 中工作?