5

我正在尝试在 delphi 中做一个“愤怒的 http 下载器”,但 TIdHttpCli 不能做我想做的事。由于某种原因,它不会在许多线程中同时运行。请看一下这个问题的简单演示:

procedure HttpRequest(AParam : Integer); stdcall;
var
  lHttp: TIdHttp;
begin
  lHttp := TIdHttp.Create(nil);
  {
  lHttp.Get(
    'http://stackoverflow.com/questions/15977505/',
    TMemoryStream.Create
  );
  }
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
  tid: DWORD;
begin
  for i := 0 to 4 do
    CreateThread(nil, 0, @HttpRequest, nil, 0, tid);
end;

David Heffernan 编辑:我简化了问题中的代码。这段代码仍然表现出这种行为。我的测试环境是 XE3 和随 XE3 一起交付的 Indy。

4

1 回答 1

8

您有一个多线程应用程序。为了让内存管理器工作,多线程应用程序必须设置IsMultiThreadTrue. 如果您的线程基于TThread.

文档中:

IsMultiThread 设置为 True 表示内存管理器应该支持多个线程。IsMultiThread 由 BeginThread 和类工厂设置为 True。

因为您正在调用原始 Windows API CreateThread,而不是使用 RTL 支持的线程例程,所以系统中没有任何内容设置IsMultiThreadTrue. 因此内存管理器假定只有一个线程,并且不会锁定对内存管理器的共享数据结构的访问。因此,您观察到的问题。

如果您只是IsMultiThread := True在启动时设置,您的代码将完美运行。或者切换到使用TThread基于线程。

请注意,您的问题与 Indy 完全无关。您只需在线程中分配堆内存即可看到此失败。这个程序每次在我的系统上都会死掉:

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

function HttpRequest(AParam : Integer): DWORD; stdcall;
var
  i: Integer;
  P: Pointer;
begin
  Result := 0;
  for i := 1 to 100000 do
    GetMem(P, 1);
end;

var
  i: Integer;
  tid: DWORD;

begin
  try
    //IsMultiThread := True;//include this line to make program correct
    for i := 0 to 15 do
      CreateThread(nil, 0, @HttpRequest, nil, 0, tid);
  except
    on E:Exception do
      Writeln(E.Message);
  end;
  Readln;
end.
于 2013-04-12T19:17:38.843 回答