multithreading - 如何进行 Mutlithreded idhttp 调用以在 StringList 上工作

标签 multithreading http delphi delphi-xe8

我是线程的新手,我有一个包含字符串的列表。我的目标是让多个线程对这个列表起作用,这个代码只适用于一个线程,因为我目前正在学习,但是当我按下开始按钮时我得到了 AV。

type
  TDemoThread = class(TThread)
  private
    procedure Abort;
  protected
    procedure Execute; override;
  public
    List: TStringList;
  end;

procedure TfrmMain.StartButton1Click(Sender: TObject);
var
  i: integer;
  List: Tstrings;
begin
  for i := 0 to memo1.Lines.Count - 1 do
  begin
    List := TStringList.Create;
    List.Add(memo1.Lines.Strings[i]);
  end;

  Thread := TDemoThread.Create(True);
  Thread.FreeOnTerminate := True;
  Thread.Start;
end;

procedure TDemoThread.Execute;
var
  lHTTP: TIdHTTP;
  i: integer;
  X: Tstrings;
begin
  inherited;
  if Terminated then
    Exit;

  lHTTP := TIdHTTP.Create(nil);
  X := TStringList.Create;
  lHTTP.ReadTimeout := 30000;
  lHTTP.HandleRedirects := True;

  for i := 0 to List.Count - 1 do
    try
      X.Text := lHTTP.Get('https://instagram.com/' + List.Strings[i]);
      S := ExtractDelimitedString(X.Text);
      X.Clear;
      TThread.Synchronize(nil,
        procedure
        begin
          frmMain.Memo2.Lines.Add(List.Strings[i] + ' : ' + S);
        end);
    finally
    end;
end;

最佳答案

您的问题是您从未分配给线程类的 List 成员:

type
  TDemoThread = class(TThread)
  private
    procedure Abort;
  protected
    procedure Execute; override;
  public
    List: TStringList; <-- never assigned to, hence always nil
  end;

因此访问冲突。

看起来您正在尝试将 memo1 的内容传递给线程。我会这样做:

type
  TDemoThread = class(TThread)
  private
    FData: TStringList;
  protected
    procedure Execute; override;
  public
    constructor Create;
    destructor Destroy; override;
  end;

constructor TDemoThread.Create(Data: TStrings);
begin
  inherited Create(False);
  FData := TStringList.Create;
  FData.Assign(Data);
  FreeOnTerminate := True;
end;

destructor TDemoThread.Destroy;
begin
  FData.Free;
  inherited;
end;

procedure TDemoThread.Execute;
var
  lHTTP: TIdHTTP;
  i: integer;
  X: TStrings;
begin
  inherited;
  if Terminated then
    Exit;

  lHTTP := TIdHTTP.Create(nil);
  X := TStringList.Create;
  lHTTP.ReadTimeout := 30000;
  lHTTP.HandleRedirects := True;

  for i := 0 to FData.Count - 1 do
    try
      X.Text := lHTTP.Get('https://instagram.com/' + FData[i]);
      S := ExtractDelimitedString(X.Text);
      X.Clear;
      TThread.Synchronize(nil,
        procedure
        begin
          frmMain.Memo2.Lines.Add(FData[i] + ' : ' + S);
        end);
    finally
    end;
end;

procedure TfrmMain.StartButton1Click(Sender: TObject);
begin
  TDemoThread.Create(memo1.Lines);
end;

创建暂停然后立即启动是没有意义的。也不允许在启动后保留对 FreeOnTerminate 线程的引用,因此我删除了它。

TDemoThread.Execute 中的代码会泄漏,除非您专门在 ARC 平台上运行。 try/finally 毫无意义。而且您不需要字符串列表来保存单个 string。假设您没有使用 ARC,它应该是:

procedure TDemoThread.Execute;
var
  lHTTP: TIdHTTP;
  i: integer;
  S: string;
begin
  if Terminated then
    Exit;

  lHTTP := TIdHTTP.Create(nil);
  try
    lHTTP.ReadTimeout := 30000;
    lHTTP.HandleRedirects := True;

    for i := 0 to FData.Count - 1 do
    begin
      S := ExtractDelimitedString(lHTTP.Get('https://instagram.com/' + FData[i]));
      TThread.Synchronize(nil,
        procedure
        begin
          frmMain.Memo2.Lines.Add(FData[i] + ' : ' + S);
        end);
    end;
  finally
    lHTTP.Free;
  end;
end;

关于multithreading - 如何进行 Mutlithreded idhttp 调用以在 StringList 上工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39096452/

相关文章:

android - 我的 "MyException"显示 Toast 在抛出线程时会导致问题。我应该如何重新组织异常处理?

python - 如何将线程局部变量与 ThreadPoolExecutor 一起使用?

windows - 当回收站已满时,ShFileOperation 会做什么?

java - 如果我依赖于缓慢的服务,如何避免花费处理器时间来等待它?

c++ - 如何解析 HTTP POST(文件上传)流?

security - 编写HTTP代理时,需要考虑哪些安全问题?

api - 具有经过身份验证的用户的 REST api 的无状态性

delphi - Indy 10 Http 服务器示例

delphi - 在 Delphi 中的多个应用程序之间共享对象

java - 在等待退出信号时处理InterruptedException(Android中的错误?)