【问题标题】:C++Builder - Correct way to take action on application startupC++Builder - 在应用程序启动时采取行动的正确方法
【发布时间】:2015-04-13 01:04:43
【问题描述】:

使用 C++Builder XE5。

我的主窗体有一个 Indy 阻塞套接字,我想在应用程序启动并显示主窗体后立即连接并阻塞它。

这样做的正确方法是什么?

在以前的版本或 C++Builder 中,OnCreateAfterConstruction 都不可靠。通常我将这样的代码放在主.cpp 文件中,就在Application->Run() 之前,但是这里不合适,因为我要阻塞(并依赖TIdAntifreeze 进行消息处理)。

我想到的一种方法是定义自定义窗口消息并将其发布给自己,但我想知道是否有“正确”的方式。

【问题讨论】:

  • 很久没用过c++builder了,不过我一般都是靠定时器来做的。
  • @sp2danny 是的,那是我最初的解决方案,但计时器通过 windows 消息工作,所以我认为它相当于自定义 windows 消息的想法

标签: c++builder indy vcl c++builder-xe5


【解决方案1】:

我的主窗体有一个 Indy 阻塞套接字,我想在应用程序启动并显示主窗体后立即连接并阻塞它。

您真的需要在主 UI 线程中执行阻塞 I/O 吗?阻塞操作,例如 Indy 的套接字 I/O,应该在工作线程中完成。

如果主线程在处理 UI 消息时需要阻塞套接字操作,您可以通过 CreateEvent()MsgWaitForMultipleObject() 在循环中使用可等待事件对象,仅当有消息要处理时才调用 Application->ProcessMessages() ,当事件发出信号时打破循环。不过,这通常不是最好的选择。一个事件驱动模型,其中工作线程通知主线程活动/结果,将是一个更好的选择。你真的不应该为任何事情阻塞主 UI 线程。

这样做的正确方法是什么?

我建议让 MainForm 构造函数创建一个工作线程,然后该线程可以管理套接字操作并在需要时与主 UI 同步。

在以前的版本或 C++Builder 中,OnCreate 和 AfterConstruction 都不可靠。

AfterConstruction() 是可靠的,而且一直都是。只有 OnCreate 事件是不可靠的,并且永远不应该在 C++ 中使用构造函数来代替。

通常我将这样的代码放在主 .cpp 文件中,就在 Application->Run() 之前,但是这里不合适,因为我要阻塞(并依赖 TIdAntifreeze 进行消息处理)。

你真的不应该依赖TIdAntiFreeze,工作线程是更好的选择。

我想到的一种方法是定义一个自定义窗口消息并将其发布给自己

这会奏效。我自己有时也会使用这种技术。请注意,这是一个基于HWND 的解决方案,因此您需要确保在发布消息之后以及从消息队列中检索到之前,您发布的HWND 不会被销毁/重新创建。如果您使用 MainForm 的 HWND,请在 OnShow 事件中发布消息。更好的选择是使用AllocateHWnd() 为您的自定义消息创建专用的HWND

【讨论】:

  • 您的第一个段落听起来像是在描述通过使用阻塞套接字和线程来模拟异步套接字。而 Indy 介绍文档详细讨论了阻塞套接字的好处,而异步套接字是一种 hack .
  • 我对@9​​87654333@的理解是反正和MsgWaitForMultipleObject基本一样,对吗?这个应用程序的主要目的是监视这个套接字,它除了等待数据进来并根据该数据在主窗体上显示内容之外实际上并没有做任何其他事情。所以在这个阶段我会坚持使用主线程块/防冻,但如果应用程序的范围扩大,那么我会按照你的建议将套接字移动到另一个线程。
  • @MattMcNabb:我描述的是与主 UI 线程相关的异步行为,而不是与 socket I/O 本身相关的。在线程中执行同步套接字 I/O,然后与 UI 线程异步交互。这与介绍文档所说的没有什么不同。
  • @MattMcNabb:TIdAntiFreezeMsgWaitForMultipleObjects() 并不真正相似。 TIdAntiFreeze 提供了一个钩子,因此在主线程中运行的 Indy 代码可以在套接字调用之前/之后直接调用 Application.ProcessMessage(),例如在读/写循环中。但是即使没有待处理的消息,也会调用ProcessMessages()。对于MsgWaitForMultipleObjects(),套接字代码将在不同的线程中运行,并且在等待套接字线程时会监视等待线程的消息队列,因此只有在消息实际处于挂起状态时才能调用ProcessMessages()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
  • 2011-09-17
  • 2014-07-21
  • 2016-08-15
  • 2014-08-27
相关资源
最近更新 更多