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

use*_*868 5 delphi multithreading 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;
Run Code Online (Sandbox Code Playgroud)

David Heffernan编辑:我简化了问题中的代码.此代码仍然显示该行为.我的测试环境是XE3,Indy与XE3一起交付.

Dav*_*nan 8

您有一个多线程应用程序.为了使内存管理器能够工作,必须将多线程应用程序设置IsMultiThreadTrue.如果基于线程,则会发生这种情况TThread.

文档:

IsMultiThread设置为True表示内存管理器应支持多个线程.IsTultiThread由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.
Run Code Online (Sandbox Code Playgroud)

  • 除了已经说过的内容之外,我只想指出,在Paulo的代码和David的代码中,`HttpRequest()`被声明为错误.它需要是一个函数,而不是一个过程:`function HttpRequest(AParam:Pointer):DWORD; stdcall;`当你签名不匹配时,如果你不小心,可能会导致次要症状. (3认同)