如何防止线程冻结 Delphi 中的主应用程序
how to prevent a thread to freeze the main app in Delphi
我正在做一个 Delphi 项目。我创建了一个 class,它可以帮助我在线程内连接到网络;
我有一个问题。此线程冻结主应用程序,直到整个响应出现。
所以我需要你的帮助来克服这个挑战。
Web.pas
unit Web;
interface
uses
SysUtils, Classes, IdBaseComponent, Dialogs,
IdComponent,
IdTCPConnection,
IdTCPClient,
IdHTTP,
idMultipartFormData;
type
TCallBack = reference to procedure(res: String);
type
TWebThread = class(TThread)
private
iniRes, iniURL: String;
iniParams: TStringList;
iniCallBack: TCallBack;
Error : String;
// var iniCallBack: reference to procedure(arg1:string);
public
constructor Create(url:String; Params:TStringList; CallBack:TCallBack);
// destructor Destroy; override;
procedure Execute(); override;
end;
implementation
constructor TWebThread.Create(url:String; Params:TStringList; CallBack:TCallBack);
begin
FreeOnTerminate := True;
inherited Create(false);
Self.FreeOnTerminate := True;
Self.iniURL := url;
Self.iniCallBack := CallBack;
Self.iniParams := TStringList.Create;
iniParams.Assign(Params);
end;
procedure TWebThread.Execute();
var
lParam: TIdMultipartFormDataStream;
IHTTP: TIDHTTP;
i:Integer;
begin
// inherited;
IHTTP := TIDHTTP.Create(nil);
lParam := TIdMultipartFormDataStream.Create;
IHTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36';
for i := 0 to iniParams.Count-1 do
begin
lParam.AddFormField(iniParams.Names[i], iniParams.ValueFromIndex[i]);
end;
try
try
iniRes := IHTTP.Post(iniURL, lParam);
Synchronize(PROCEDURE
BEGIN
iniCallBack(iniRes);
END);
Except
on E: Exception do
Error := E.ClassName + ' error raised, with message : ' + E.Message;
end;
finally
FreeAndNil(IHTTP);
FreeAndNil(iniParams);
end;
end;
end.
下面是使用方法:
procedure TMainForm.Button2Click(Sender: TObject);
var
Params: TStringList;
Web: TWebThread;
begin
Params := TStringList.Create;
Params.AddPair('Name','Ahmad');
Params.AddPair('Family','Khaliq');
Web := TWebThread.Create('http://localhost/get.php', Params,procedure (res : string)
begin
Label1.Caption := res;
end);
Web.Execute;
end;
这是我的问题:
此线程冻结主应用程序,直到它收到整个 idHTTP 响应
我认为(但尚未证实)原因是您从主线程显式调用 Web.Execute。
线程的 Execute 方法应该(并且会自动)从线程本身调用 - 它不应该从主线程调用。
因此请尝试删除 Web.Execute 调用,看看是否不能解决您遇到的问题。
同步代码摘录:
if (CurrentThread.ThreadID = MainThreadID) and not (QueueEvent and ForceQueue) then
begin
if Assigned(ASyncRec.FMethod) then
ASyncRec.FMethod()
else if Assigned(ASyncRec.FProcedure) then
ASyncRec.FProcedure();
end else
我正在做一个 Delphi 项目。我创建了一个 class,它可以帮助我在线程内连接到网络;
我有一个问题。此线程冻结主应用程序,直到整个响应出现。
所以我需要你的帮助来克服这个挑战。
Web.pas
unit Web;
interface
uses
SysUtils, Classes, IdBaseComponent, Dialogs,
IdComponent,
IdTCPConnection,
IdTCPClient,
IdHTTP,
idMultipartFormData;
type
TCallBack = reference to procedure(res: String);
type
TWebThread = class(TThread)
private
iniRes, iniURL: String;
iniParams: TStringList;
iniCallBack: TCallBack;
Error : String;
// var iniCallBack: reference to procedure(arg1:string);
public
constructor Create(url:String; Params:TStringList; CallBack:TCallBack);
// destructor Destroy; override;
procedure Execute(); override;
end;
implementation
constructor TWebThread.Create(url:String; Params:TStringList; CallBack:TCallBack);
begin
FreeOnTerminate := True;
inherited Create(false);
Self.FreeOnTerminate := True;
Self.iniURL := url;
Self.iniCallBack := CallBack;
Self.iniParams := TStringList.Create;
iniParams.Assign(Params);
end;
procedure TWebThread.Execute();
var
lParam: TIdMultipartFormDataStream;
IHTTP: TIDHTTP;
i:Integer;
begin
// inherited;
IHTTP := TIDHTTP.Create(nil);
lParam := TIdMultipartFormDataStream.Create;
IHTTP.Request.UserAgent := 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36';
for i := 0 to iniParams.Count-1 do
begin
lParam.AddFormField(iniParams.Names[i], iniParams.ValueFromIndex[i]);
end;
try
try
iniRes := IHTTP.Post(iniURL, lParam);
Synchronize(PROCEDURE
BEGIN
iniCallBack(iniRes);
END);
Except
on E: Exception do
Error := E.ClassName + ' error raised, with message : ' + E.Message;
end;
finally
FreeAndNil(IHTTP);
FreeAndNil(iniParams);
end;
end;
end.
下面是使用方法:
procedure TMainForm.Button2Click(Sender: TObject);
var
Params: TStringList;
Web: TWebThread;
begin
Params := TStringList.Create;
Params.AddPair('Name','Ahmad');
Params.AddPair('Family','Khaliq');
Web := TWebThread.Create('http://localhost/get.php', Params,procedure (res : string)
begin
Label1.Caption := res;
end);
Web.Execute;
end;
这是我的问题: 此线程冻结主应用程序,直到它收到整个 idHTTP 响应
我认为(但尚未证实)原因是您从主线程显式调用 Web.Execute。
线程的 Execute 方法应该(并且会自动)从线程本身调用 - 它不应该从主线程调用。
因此请尝试删除 Web.Execute 调用,看看是否不能解决您遇到的问题。
同步代码摘录:
if (CurrentThread.ThreadID = MainThreadID) and not (QueueEvent and ForceQueue) then
begin
if Assigned(ASyncRec.FMethod) then
ASyncRec.FMethod()
else if Assigned(ASyncRec.FProcedure) then
ASyncRec.FProcedure();
end else