Thread.Sleep() 和 Thread.SpinWait() 有什么区别?

3
我有一个WinForm应用程序,使用BackGroundWorker创建TCP客户端并将一些数据发送到远程服务器。当套接字完成关闭连接并从DoWork子程序退出后,在RunWorkerCompleted子程序中,我必须等待来自远程服务器的数据包,因此我始终运行一个填充Friend String类型变量并使用Boolean类型变量(标志)指示整个数据包已接收的TCP服务器。
因此,我必须等待该标志变为True,以处理必须在String类型变量中的数据;但我不想挂起GUI,因此我看到存在一种称为SpinWait的方法。
所以,这段代码可以工作吗?
如果5分钟后标志没有变为True,有没有办法退出循环?
Private Sub BGW1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BGW1.RunWorkerCompleted
        While Not AckReady
            System.Threading.Thread.SpinWait(500)
        End While

        'Here process the received data from TCP server

        TmrReport.Start()

End Sub 

另外一个问题是,多少次迭代表示500毫秒?

1
那不起作用,当服务器无响应时会冻结您的用户界面。如果您已经在使用工作线程,那么最好让它等待响应。 - Hans Passant
好的,那么我将while循环移动到DoWork子程序中,并使用Sleep代替SpinWait。我是对的吗? - E_Blue
我不太清楚为什么你想要睡觉。当你得到响应后,就完成了。 - Hans Passant
@HansPassant 远程服务器的响应需要一段时间,可能会在5秒到50秒之间变化。因此,我必须等待答案来处理数据并向远程服务器发送新数据。 - E_Blue
嗯,这就是BackgroundWorker的用处,不要让DoWork事件处理程序退出,直到你得到那个响应为止。顺便说一下,BeginRead和async/await也能完成这项任务。 - Hans Passant
1个回答

3
根据文档: Thread.SpinWait Method SpinWait 方法用于实现锁。.NET Framework 中的类,例如 Monitor 和 ReaderWriterLock 在内部使用该方法。SpinWait 本质上是将处理器放入非常紧密的循环中,循环次数由 iterations 参数指定。因此等待持续的时间取决于处理器的速度。
相比之下,Sleep 方法不同。 调用 Sleep 的线程会放弃其当前的处理器时间片,即使指定的时间间隔为零。为 Sleep 指定非零间隔会使线程在经过时间间隔之前不再由线程调度程序考虑。
因此,Sleep 基本上释放了处理器,以便其他东西可以使用它,而 SpinWait 运行一个循环,使处理器保持忙碌(并锁定其他线程)。

好的,那么在 SpinWait 循环期间整个服务器会挂起吗? - E_Blue
1
SpinWait() 只是在等待时让调用线程保持繁忙状态。该线程仍然受任务调度的影响。Sleep() 将调用线程置于睡眠状态,并将其从任务调度中移除,直到它唤醒。 - Remy Lebeau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接