2

这段代码似乎不是获取线程结果的正确方法,即使表单没有冻结,我可以执行不同的其他任务,也许是另一个请求,所以线程数不会一直相等,最多可能同时有 5 个请求,但不依赖于彼此。

这应该如何以“好”的方式完成?

function TEApi.FApiRequest(Request: string) : string;
var
  RequestThread : TApiSecureRequest; {TThread}
begin
  RequestThread := TApiSecureRequest.Create(Self, Request);
  while(NOT RequestThread.Terminated) do
    Application.ProcessMessages;
  Result := RequestThread.FResponse;
  RequestThread.Free;
end;

procedure TApiSecureRequest.Execute;
begin
  {do some HTTP requests, which is freezing the Mainform without threading}
  FResponse = Result_of_execution;
  Terminate;
end;
4

1 回答 1

4

不要使用Application.ProcessMessages. 这是糟糕的代码设计的例子,你应该避免使用它。

相反,使用线程回调或消息。例子:

uAPISecureRequestThread.pas

unit uAPISecureRequestThread;

interface

uses
  System.Classes;

type
  TApiSecureRequestThread = class(TThread)
  private
    FResponse: String;
  protected
    procedure Execute; override;
  public
    constructor Create;

    property Response: String read FResponse;
  end;

implementation

constructor TApiSecureRequestThread.Create;
begin
  inherited Create(TRUE);
  FreeOnTerminate := TRUE; // automatically free thread on terminate
end;

procedure TApiSecureRequestThread.Execute;
begin
  // do the work here and assign result to FResponse
end;

end.

uMainForm.pas

unit uMainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TfrmMain = class(TForm)
    btCreateThread: TButton;
    procedure btCreateThreadClick(Sender: TObject);
  private
    procedure ASRThreadTerminate(Sender: TObject);
  public
  end;

var
  frmMain: TfrmMain;

implementation

{$R *.dfm}

uses
  uApiSecureRequestThread;

procedure TfrmMain.btCreateThreadClick(Sender: TObject);
var
  asr_thread: TApiSecureRequestThread;
begin
  asr_thread := TApiSecureRequestThread.Create;
  try
    asr_thread.OnTerminate := ASRThreadTerminate;
    asr_thread.Start;
  except
    asr_thread.Free;
  end;
end;

procedure TfrmMain.ASRThreadTerminate(Sender: TObject);
var
  asr_thread: TApiSecureRequestThread;
begin
  asr_thread := Sender as TApiSecureRequestThread;

  // process asr_thread.Response here
end;

end.
于 2013-09-08T15:10:49.000 回答