2013-04-12 5 views
5

Ich versuche seit einiger Zeit eine "böse http Downloader" in Delphi, aber TIdHttpCli kann nicht tun, was ich will. Aus irgendeinem Grund wird es nicht in vielen Threads gleichzeitig ausgeführt. Schauen Sie sich hier eine der einfachen Demonstration dieses Problems:Zugriffsverletzung mit TIdHttp läuft auf vielen Threads zur gleichen Zeit

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 edit: ich den Code in der Frage vereinfacht. Dieser Code zeigt immer noch das Verhalten an. Meine Testumgebung war XE3 mit dem Indy, der mit XE3 ausgeliefert wurde.

+1

@PauloParedes - TThread, wie von David vorgeschlagen. –

Antwort

8

Sie haben eine Anwendung mit mehreren Threads. Damit der Speichermanager funktioniert, müssen Multithread-Anwendungen IsMultiThread auf True setzen. Dies passiert, wenn Sie Ihre Threads auf TThread basieren.

Vom documentation:

IsMultiThread auf True gesetzt ist, um anzuzeigen, dass der Speicher-Manager mehrere Threads unterstützen sollte. IsMultiThread wird von BeginThread und Klassenfactorys auf True gesetzt.

Weil Sie den rohe Windows-API CreateThread, fordern und nicht mit der RTL-Thread-Routinen unterstützt, nichts mehr im System setzt IsMultiThread-True. Und so geht der Speichermanager davon aus, dass es nur einen einzigen Thread gibt, und sperrt den Zugriff auf die freigegebenen Datenstrukturen des Speichermanagers nicht. Daher die Probleme, die Sie beobachtet haben.

Wenn Sie einfach IsMultiThread := True beim Start setzen, wird Ihr Code perfekt funktionieren. Oder wechseln Sie zu einem TThread basierten Thread.

Beachten Sie, dass Ihr Problem mit Indy überhaupt nichts zu tun hat. Sie können diesen Fehler einfach durch Zuweisen von Heapspeicher im Thread erkennen. Dieses Programm stirbt jedes Mal auf meinem System:

{$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. 
+3

Zusätzlich zu dem, was gesagt wurde, möchte ich nur darauf hinweisen, dass 'HttpRequest()' sowohl in Paulos Code als auch in Davids Code für falsch erklärt wird. Es muss eine Funktion sein, keine Prozedur: 'function HttpRequest (AParam: Pointer): DWORD; stdcall; 'Wenn Sie eine Signatur nicht zuordnen, kann dies sekundäre Symptome verursachen, wenn Sie nicht vorsichtig sind. –

+0

@David Heffernan, kann diese Idee von OP mit einer "" verärgerten Absender E-Mail "mit dem gleichen E-Mail-Konto und Senden an eine Liste von Empfängern in einer" Memo "-Komponente oder SMTP-Server nicht unterstützt es mit einem gleichen account ? (In anderen Worten, ich muss mehrere E-Mail-Konten haben und für jeden 1 einen neuen Thread erstellen?). – Saulo

Verwandte Themen