使用TIdHttp同时在多个线程上运行访问冲突

时间:2013-04-12 17:33:11

标签: multithreading delphi http

我正在尝试在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,其中Indy是随XE3一起提供的。

1 个答案:

答案 0 :(得分:8)

您有一个多线程应用程序。为了使内存管理器正常工作,多线程应用程序必须将IsMultiThread设置为True。如果您将线程基于TThread

,就会发生这种情况

来自documentation

  

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

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

如果您只是在启动时设置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.