我有一个旧的代码,我想升级到Delphi XE.
我有一个关于Resume的编译器警告,我想用Start替换它,但程序崩溃.
我有一个关于Resume的编译器警告,我想用Start替换它,但程序崩溃.
- constructor THTTPGetThread.Create(aAcceptTypes,aAgent,aURL,aFileName,aUserName,aPassword,aPostQuery,aReferer: String; aBinaryData,aUseCache: Boolean; aProgress: TOnProgressEvent; aToFile: Boolean);
- begin
- FreeOnTerminate := True;
- inherited Create(True);
- FTAcceptTypes := aAcceptTypes;
- FTAgent := aAgent;
- FTURL := aURL;
- FTFileName := aFileName;
- FTUserName := aUserName;
- FTPassword := aPassword;
- FTPostQuery := aPostQuery;
- FTReferer := aReferer;
- FTProgress := aProgress;
- FTBinaryData := aBinaryData;
- FTUseCache := aUseCache;
- FTToFile := aToFile;
- Resume; <------------ works,but I get compiler warning
- //Start; <------------ doesn't work
- end;
当我使用START时我得到的错误是:“线程错误:句柄无效(6)”.
我不想复杂的东西(冻结/同步线程).我只想从互联网上下载一个文件,而不会阻止GUI.
解决方法
简单的答案是,您不应该创建此线程已暂停,因为您希望它立即启动.删除对Start的调用,并将False传递给继承的构造函数.
请注意,直到所有构造函数都运行到完成为止,线程才会启动,因此其意义与您发布的代码相同.
- procedure TThread.AfterConstruction;
- begin
- if not FCreateSuspended and not FExternalThread then
- InternalStart(True);
- end;
- procedure TThread.InternalStart(Force: Boolean);
- begin
- if (FCreateSuspended or Force) and not FFinished and not FExternalThread then
- begin
- FSuspended := False;
- FCreateSuspended := False;
- if ResumeThread(FHandle) <> 1 then
- raise EThread.Create(SThreadStartError);
- end
- else
- raise EThread.Create(SThreadStartError);
- end;
- procedure TThread.Start;
- begin
- InternalStart(False);
- end;
您的代码使用CreateSuspended = True调用继承的构造函数.这将FCreateSuspended设置为True.然后在TThread.AfterConstruction运行之前调用Start.这成功地启动了线程,但是至关重要的是将FCreateSuspended置于False.然后当TThread.AfterConstruction它尝试恢复线程失败,因为它已经在运行.
我认为Delphi代码很好,因为从构造函数调用Start是不正确的.您需要确保所有构造函数都已运行,并且派生类构造函数在调用Start之后运行.你没有任何派生类,但这不是要点 – 不支持从构造函数调用开始.
最重要的是你应该创建这个线程不被挂起,并且允许你从AfterConstruction代表你调用Start.