线程中的 Indy TCP 客户端
Indy TCP client in thread
从 this thread 开始,我正在尝试制作一个 C++Builder XE5 应用程序:
- 一个主窗体
- 一个
TIdTCPClient
- a
TThread
用于 TIdTCPClient
的连接,打开套接字,发送请求,然后无限期地监听多个响应
- 套接字上发生的操作将导致主窗体上的更新
我找不到任何例子;据我所知,从 Indy Demos 页面链接的示例都没有在其客户端中使用任何线程。
我的问题是:
- TIdTCPClient应该放在主窗体上(作为设计时组件),还是应该作为线程的成员变量class?
- 在 TIdTCPClient 触发的事件中,事件处理程序中的代码(它们是我的主窗体的成员函数)是否需要同步?
- 主VCL线程和客户端线程对TIdTCPClient对象进行函数调用是否安全?
目前,我在主窗体上执行操作以响应每个事件,并响应在套接字上接收数据。目前,我的代码充满了临时变量和存根函数,因为 Synchronize
需要一个 void(void)
闭包,这简直是意大利面条。所以我想知道我是否采取了根本错误的方法。
Should the TIdTCPClient be on the main form (as a design time component), or should it be a member variable of the thread class?
两者都可以。重要的是您在工作线程的上下文中调用 Connect()
和其他 I/O 方法(在其 Execute()
方法内)。
In the events fired by the TIdTCPClient , does the code in the event handlers (which are member functions of my main form) need to be Synchronized?
是,如果他们正在访问 UI 控件或其他必须保护的共享数据。
Is it safe for both the main VCL thread and the client thread to make function calls on the TIdTCPClient object?
这取决于特定的调用(例如,从主线程发送出站数据,同时在工作线程中读取入站数据,至少在客户端连接时),但我不建议您依赖它。您应该只在工作线程中保留所有与客户端相关的操作。
At the moment my code is full of temporary variables and stub functions because Synchronize requires a void(void) closure and it is quite spaghetti.
您可以使用 Indy 的 TIdSync
/TIdNotify
classes 来帮助您更好地组织意大利面条代码。例如,从 TIdSync
派生一个 class,将您的变量移入其中,并覆盖其虚拟 DoSynchronize()
方法以根据需要调用您的 Form 方法。然后你可以创建你的实例 class,如果需要填充它的变量,调用它的 Synchronize()
方法,如果需要读取它的变量,然后释放它。
#include <IdSync.hpp>
class TMySync : public TIdSync
{
protected:
virtual void __fastcall DoSynchronize();
public:
// variables...
};
void __fastcall TMySync::DoSynchronize()
{
// call Form methods, use variables as needed...
}
void __fastcall TMyThread::Execute()
{
//...
TMySync *sync = new TMySync;
// set variables as needed...
sync->Synchronize();
// read variables as needed...
delete sync;
//...
}
从 this thread 开始,我正在尝试制作一个 C++Builder XE5 应用程序:
- 一个主窗体
- 一个
TIdTCPClient
- a
TThread
用于TIdTCPClient
的连接,打开套接字,发送请求,然后无限期地监听多个响应 - 套接字上发生的操作将导致主窗体上的更新
我找不到任何例子;据我所知,从 Indy Demos 页面链接的示例都没有在其客户端中使用任何线程。
我的问题是:
- TIdTCPClient应该放在主窗体上(作为设计时组件),还是应该作为线程的成员变量class?
- 在 TIdTCPClient 触发的事件中,事件处理程序中的代码(它们是我的主窗体的成员函数)是否需要同步?
- 主VCL线程和客户端线程对TIdTCPClient对象进行函数调用是否安全?
目前,我在主窗体上执行操作以响应每个事件,并响应在套接字上接收数据。目前,我的代码充满了临时变量和存根函数,因为 Synchronize
需要一个 void(void)
闭包,这简直是意大利面条。所以我想知道我是否采取了根本错误的方法。
Should the TIdTCPClient be on the main form (as a design time component), or should it be a member variable of the thread class?
两者都可以。重要的是您在工作线程的上下文中调用 Connect()
和其他 I/O 方法(在其 Execute()
方法内)。
In the events fired by the TIdTCPClient , does the code in the event handlers (which are member functions of my main form) need to be Synchronized?
是,如果他们正在访问 UI 控件或其他必须保护的共享数据。
Is it safe for both the main VCL thread and the client thread to make function calls on the TIdTCPClient object?
这取决于特定的调用(例如,从主线程发送出站数据,同时在工作线程中读取入站数据,至少在客户端连接时),但我不建议您依赖它。您应该只在工作线程中保留所有与客户端相关的操作。
At the moment my code is full of temporary variables and stub functions because Synchronize requires a void(void) closure and it is quite spaghetti.
您可以使用 Indy 的 TIdSync
/TIdNotify
classes 来帮助您更好地组织意大利面条代码。例如,从 TIdSync
派生一个 class,将您的变量移入其中,并覆盖其虚拟 DoSynchronize()
方法以根据需要调用您的 Form 方法。然后你可以创建你的实例 class,如果需要填充它的变量,调用它的 Synchronize()
方法,如果需要读取它的变量,然后释放它。
#include <IdSync.hpp>
class TMySync : public TIdSync
{
protected:
virtual void __fastcall DoSynchronize();
public:
// variables...
};
void __fastcall TMySync::DoSynchronize()
{
// call Form methods, use variables as needed...
}
void __fastcall TMyThread::Execute()
{
//...
TMySync *sync = new TMySync;
// set variables as needed...
sync->Synchronize();
// read variables as needed...
delete sync;
//...
}