【问题标题】:Why does a TidTCPClient in a separate thread block the main thread?为什么单独线程中的 TidTCPClient 会阻塞主线程?
【发布时间】:2011-03-22 15:41:02
【问题描述】:

一个单独的线程创建一个 TidTCPClient 和一个 TTimer。 TTimer 设置为 3s,如果 TCPClient 未连接,则调用 TCPClient.Connect。
如果没有要连接的服务器,这将导致每 3 秒尝试连接一次。

主线程 (UI) 什么都不做,但是如果我用鼠标抓住窗口并在屏幕上缓慢移动它,它会每 3 秒卡住大约 2 秒,然后它会跳转到鼠标光标位置并再次跟随鼠标,直到发生下一次连接尝试。

换句话说,当 TCPClient 尝试连接时,主线程似乎被阻塞了。

为什么会发生这种情况,即使 TCPClient 在它的单独线程中?

【问题讨论】:

  • 组件不存在于线程中,它们存在于内存中。代码在你调用它的线程中执行。

标签: delphi delphi-2009 indy10


【解决方案1】:

您的 TTimer 通过接收 WM_TIMER 消息来工作;这些消息是使用 VCL 的主消息泵在 VCL 线程中分派的。 3 秒后,您的 TTimer.OnTimer 事件在主线程中运行,因此对 Connect 的调用在 VCL 主线程中运行。

你被阻止是因为你没有线程!

【讨论】:

  • 只有当TTimer 是在主线程上下文中创建时才成立,例如在线程的构造函数中。为了让 TTimer 在线程内运行,需要在线程的 Execute() 方法内创建它,然后线程需要自己的消息循环,以便正确分派 WM_TIMER 消息。即使这样,TTimer 也不是线程安全的(因为它在内部使用了AllocateHWnd()),所以你应该直接使用SetTimer(),甚至可以通过CreateWaitableTimer() 使用等待定时器,通过timeSetEvent() 使用多媒体定时器,甚至只是一个手动睡眠循环。
  • 是的,定时器是在线程的构造函数中创建的。感谢您的解释
猜你喜欢
  • 2016-06-26
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 2021-11-12
  • 2020-01-02
  • 2021-08-29
  • 2018-02-16
相关资源
最近更新 更多