2013-06-04 9 views
5

Ich versuche, ein indy TIdHttp in einem Thread zu setzen, haben ich das versucht:für Gewinde Warten ohne Einfrieren der Anwendung

type 
    TSendThread = class(TThread) 
    private 
    { Private declarations } 
    protected 
    procedure Execute; override; 
    public 
    http : TIdHTTP; 
    URL : String; 
    Method : String; 
    property ReturnValue; 
    end; 

procedure TSendThread.Execute; 
begin 
    form1.Memo1.lines.Add(http.Get(URL)); 
    ReturnValue := 1; 
end; 

Und im Haupt:

procedure TForm1.Button1Click(Sender: TObject); 
var t : TSendThread; 
begin 
    t := TSendThread.Create(true); 
    t.URL := 'http://www.url.com/'; 
    t.http := http; 
    t.Start; 
    showmessage(IntToStr(t.ReturnValue)); 
end; 

Mein Problem Hier ist, dass die nächste Anweisung ausgeführt wird (showmessage), ohne den Thread zu warten, ich habe versucht, die "WaitFor" zu verwenden, aber es friert die Anwendung ein.

Gibt es eine andere Problemumgehung?

Vielen Dank.

+3

Wenn Sie „warten, dass es“ zu beenden, gibt es keine Notwendigkeit, sie in einem Thread an erster Stelle zu setzen. Threads werden im Hintergrund ausgeführt, sodass die Benutzeroberfläche nicht * warten muss. –

+0

@Benjamin: Wenn Sie 'ProcessMessages' verwenden müssen, haben Sie jetzt ein neues Problem hinzugefügt. Es ist ** nie ** die richtige Lösung. –

+0

'ProcessMessages' ist OK, wenn mit Vorsicht verwendet wird – OnTheFly

Antwort

9

Verwenden Sie das TThread.OnTerminate Ereignis zu wissen, wann der Thread beendet hat:

type 
    TSendThread = class(TThread) 
    private 
    http : TIdHTTP; 
    Line: string; 
    procedure AddLine; 
    protected 
    procedure Execute; override; 
    public 
    constructor Create; reintroduce; 
    destructor Destroy; override; 
    URL : String; 
    Method : String; 
    property ReturnValue; 
    end; 

constructor TSendThread.Create; 
begin 
    inherited Create(True); 
    FreeOnTerminate := True; 
    http := TIdHTTP.Create; 
end; 

destructor TSendThread.Destroy; 
begin 
    http.Free; 
    inherited; 
end; 

procedure TSendThread.Execute; 
begin 
    Line := http.Get(URL); 
    Synchronize(AddLine); 
    ReturnValue := 1; 
end; 

procedure TSendThread.AddLine; 
begin 
    Form1.Memo1.Lines.Add(Line); 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    t : TSendThread; 
begin 
    t := TSendThread.Create; 
    t.URL := 'http://www.url.com/'; 
    t.OnTerminate := ThreadTerminated; 
    t.Start; 
end; 

procedure TForm1.ThreadTerminated(Sender: TObject); 
begin 
    ShowMessage(IntToStr(TSendThread(Sender).ReturnValue)); 
end; 

Wenn Sie eine Schleife zu warten, bis der Faden verwenden möchten beenden, ohne die Benutzeroberfläche zu blockieren, dann können Sie es so tun:

constructor TSendThread.Create; 
begin 
    inherited Create(True); 
    //FreeOnTerminate := True; // <-- remove this 
    http := TIdHTTP.Create; 
end; 

procedure TForm1.Button1Click(Sender: TObject); 
var 
    t : TSendThread; 
    h : THandle; 
begin 
    t := TSendThread.Create; 
    try 
    t.URL := 'http://www.url.com/'; 
    t.Start; 
    h := t.Handle; 
    repeat 
     case MsgWaitForMultipleObjects(1, h, 0, INFINITE, QS_ALLINPUT) of 
     WAIT_OBJECT_0: Break; 
     WAIT_OBJECT_0+1: Application.ProcessMessages; 
     WAIT_FAILED:  RaiseLastOSError; 
     else 
     Break; 
     end; 
    until False; 
    ShowMessage(IntToStr(t.ReturnValue)); 
    finally 
    t.Free; 
    end; 
end; 
+1

BenjaminWeiss hat Recht. Ich habe meine Antwort entsprechend aktualisiert. –

+0

Yep das ist, was ich auch getan habe :). Vielen Dank, seit 2 Tagen gesucht –

Verwandte Themen