我正在尝试在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一起提供的。
答案 0 :(得分:8)
您有一个多线程应用程序。为了使内存管理器正常工作,多线程应用程序必须将IsMultiThread
设置为True
。如果您将线程基于TThread
。
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.