如何防止线程冻结 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