gpt4 book ai didi

c++ - 线程中的 TIdFTP 未触发 Work 方法

转载 作者:行者123 更新时间:2023-11-28 05:32:04 25 4
gpt4 key购买 nike

我有一个用 Embarcadero 的 C++ 10 Seattle 编写的 VCL 应用程序。主线程生成一个线程来运行 TIdFTP 功能,因为如果在传输过程中连接丢失,Get 方法将无限期挂起。这个想法是检测连接是否挂起,孤立线程,并产生“重试”。我的问题是我已经在线程的 h 文件中声明了对象以及应该触发的方法(WorkBegin、WorkEnd、Work 等),如下所示....

class FTPThread : public TThread
{
protected:
void __fastcall Execute();
void __fastcall UpdateUI();
public:
__fastcall FTPThread(bool CreateSuspended);
String FTPhostname;
String FTPusername;
String FTPpassword;
String remoteDir;
String localDir;
String localTempDir;
String fileName;
TIdFTP *FTPClnt;
void __fastcall FTPClntWorkBegin(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCountMax);
void __fastcall FTPClntWorkEnd(TObject *ASender, TWorkMode AWorkMode);
void __fastcall FTPClntWork(TObject *ASender, TWorkMode AWorkMode, __int64 AWorkCount);
void __fastcall FTPClntAfterGet(TObject *ASender, TStream *AStream);

};

然后我像这样在线程的 cpp 文件中实现了 Work 函数......

void __fastcall FTPThread::UpdateUI()
{
if (FrmFTP) {
//FrmFTP->FTPProg->Max = fileSizeBytes;
FrmFTP->FTPProg->Position = ftpProgress;
FrmFTP->BringToFront();
Application->ProcessMessages();
}
}

void __fastcall FTPThread::FTPClntWorkBegin(TObject *ASender,
TWorkMode AWorkMode, __int64 AWorkCountMax) {
ftpProgress = 0;
if (FrmFTP) {
FrmFTP->FTPProg->Max = fileSizeBytes;
}
Synchronize(&UpdateUI);
}
// ---------------------------------------------------------------------------

void __fastcall FTPThread::FTPClntWorkEnd(TObject *ASender,
TWorkMode AWorkMode)

{
if (FrmFTP) {
ftpProgress = FrmFTP->FTPProg->Max;
}
Synchronize(&UpdateUI);
}
// ---------------------------------------------------------------------------

void __fastcall FTPThread::FTPClntWork(TObject *ASender, TWorkMode AWorkMode,
__int64 AWorkCount)

{
ftpProgress = AWorkCount;
Synchronize(&UpdateUI);
}
// ---------------------------------------------------------------------------

void __fastcall FTPThread::FTPClntAfterGet(TObject *ASender,
TStream *AStream) {
ftpCompletionStatus = 1;
}
// ---------------------------------------------------------------------------

这些方法都不会在 Get 开始、传输和完成时触发。知道他们为什么不开火吗?我的主线程上的相同功能运行良好。我觉得我在某种程度上没有尝试我已经实现到 TIdFTP 对象的这些方法,但我不确定如何去做。

谢谢!

最佳答案

the Get method indefinitely hangs if the connection is lost during the transfer.

它最终应该会失败。操作系统可能需要一段时间才能真正检测到丢失的连接并使打开的套接字无效,因此 I/O 操作开始报告错误。如果您不想等那么久,请确保将 ReadTimeout 属性设置为合理的超时(TIdFTP 默认设置为 1 分钟),以及TransferTimeout 属性(默认为无限)。

The idea is to detect if the connection has hung, orphan the thread, and spawn a "retry".

从不“孤立”线程。您可以简单地让主线程调用 TIdFTPAbort()Disconnect() 方法来终止正在进行的传输并关闭命令套接字。

My problem is I've declared the object in the thread's h file as well as the methods that should fire (WorkBegin, WorkEnd, Work, etc) like follows....

请勿在同步方法内调用Application->ProcessMessages()。该方法已经在主线程消息处理程序中运行,只需退出同步方法,控制权就会返回到主消息循环。

此外,您的 OnWork... 处理程序直接从主线程外部访问 FrmFTP->FTPProg->Max。这些访问也需要同步。 任何触及主 UI 的东西都需要同步。

None of these methods are ever fired as the Get begins, transfers, and completes. Any idea why they wouldn't fire?

你一开始就把它们联系起来了吗?大概 FTPClnt 是在 FTPThread::Execute() 中创建的,但它是否将您的处理程序分配给 FTPClnt->OnWork... 事件在创建 FTPClnt 之后?他们不会为你 Hook ,你必须自己做,例如:

FTPClnt = new TIdFTP;
FTPClnt->OnWorkBegin = &FTPClntWorkBegin;
FTPClnt->OnWorkEnd = &FTPClntWorkEnd;
FTPClnt->OnWork = &FTPClntWork;

The same functionality on my main thread worked fine.

如果您在设计时将一个 TIdFTP 对象放到一个 Form 上,并在对象检查器中分配它的 OnWork... 事件,那么 DFM 流系统会 Hook 在运行时创建表单时为您设置事件处理程序。

仅仅声明事件处理程序是不够的。必须有人(您或 DFM)在运行时实际连接它们

关于c++ - 线程中的 TIdFTP 未触发 Work 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39258694/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com