AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Thread abbrechen

Ein Thema von OrallY · begonnen am 10. Mai 2003 · letzter Beitrag vom 11. Mai 2003
Antwort Antwort
Benutzerbild von OrallY
OrallY

Registriert seit: 29. Apr 2003
268 Beiträge
 
#1

Thread abbrechen

  Alt 10. Mai 2003, 13:29
In einem Thread läuft ein langwieriger Prozess ab. Nun möchte ich dem User die Möglichkeit geben, den Prozess abzubrechen. Mit TThread.Terminate klappts natürlich nicht. Also habe ich mal TerminateThread ausprobiert. Manchmal hats damit geklappt, manchmal ist das Programm einfach abgestürtzt, dies war häufiger der Fall. Also habe ich eine Prozedure in der Thread-Klasse definiert, die so aussieht:
Code:
procedure TMyThread.ShutDownThread;
var
  ExitCode: Longword;
begin
  GetExitCodeThread(Handle, ExitCode);
  ExitThread(ExitCode);
end;
Wenn ich nun aber im Hauptthread diese Methode aufrufe, ist meine Anwedung niergens mehr zu sehen, scheint aber noch zu laufen, da in der IDE der "Play" Button noch gedrückt ist usw.. Welche Möglichkeit habe ich noch, einen einen langen Prozess in einem Thread abzubrechen oder ist die von mir verwendete Methode die richtige, nur mach ich was falsch?
.oO'rallY
Linux is like a tipi: no gates, no windows and a gnu-eating apache inside...
  Mit Zitat antworten Zitat
Stream

Registriert seit: 12. Jan 2003
3 Beiträge
 
#2
  Alt 10. Mai 2003, 15:03
Hallo OrallY!

Das Problemm kenne ich, und es ist auch leicht zu lösen. Das könnte zum Beispiel ein Boolean-Wert in der Thread-Klasse sein, den gibst du den Namen Cancel und setzt ihn als Public Wert ein. Beim Start des Threades setzt du diesen Wert auf false. Wenn der User nun auf den Abbrechen-Button Klickt, wird der Cancel-Bool auf true gesetzt. Jetzt musst du nur noch in deiner Execute-Prozedur eine Abfrage erstellen, ob der Thread geschlossen werden soll oder nicht.

Das sieht dann in Etwa so aus:
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
FreeOnTerminate := true;
Cancel := false;
...
if Cancel then begin
    Terminate;
    exit;
  end;
...
end;
Dein Problem dürfte dann nicht auftreten. Wenn du aber den Thread erneut starten willst musst du ihn aber erneut erstellen! Ansonsten gibt es ne dicke fette Fehlermeldung.

Tschö!
  Mit Zitat antworten Zitat
Benutzerbild von OrallY
OrallY

Registriert seit: 29. Apr 2003
268 Beiträge
 
#3
  Alt 11. Mai 2003, 10:12
Ersteinmal danke für die Hilfe! Doch muss ich dich leider enttäuschen. Dein Lösungsweg hilft mir erstens nicht weiter und zweitens ist er sogar ein wenig umständlich. Ein kurze Erläuterung:
Die Mehode Terminate eines TThread-Klasse macht nichts anderes, als einen boolischen Wert inerhalb der Klasse auf true zu setzen. Also genau das, was du mit Cancel gemacht hast. Deswegen kannst du einfach von auserhalb die Methode Terminate aufrufen und dann im Thread-Source den boolischen Wert Terminated abfragen:
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
   MyThread.Terminate;
end;

procedure TMyThread.Execute;
begin
FreeOnTerminate := true;
...
if terminated then
* * exit;
...
end;
Trotzdem danke!
.oO'rallY
Linux is like a tipi: no gates, no windows and a gnu-eating apache inside...
  Mit Zitat antworten Zitat
Benutzerbild von OrallY
OrallY

Registriert seit: 29. Apr 2003
268 Beiträge
 
#4
  Alt 11. Mai 2003, 10:16
Mein Code sieht aber in etwa so aus:
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
   Machwasverdammtlanges(beschäftigung); {kann mehrere Minuten dauern, bis die Prozedur wieder zurückkehrt}
end;
Irgendwie scheint ExitThread den Hauptthread gleich mit zu killen. Man kann ja auch keinen Handle übergeben...
.oO'rallY
Linux is like a tipi: no gates, no windows and a gnu-eating apache inside...
  Mit Zitat antworten Zitat
jbg

Registriert seit: 12. Jun 2002
3.483 Beiträge
 
Delphi 10.1 Berlin Professional
 
#5
  Alt 11. Mai 2003, 11:13
Du könntest eine Stille Exception auslösen und diese in der Execute-Funktion abfangen.

Delphi-Quellcode:
type
  EThreadExit = class(EAbort);

procedure TMyThread.HandleException
begin
 // System.ExceptObject liefert die Aktuelle Exception
  Application.ShowException(ExceptObject);
end;

procedure TMyThread.Execute;
begin
  try
    while (not Terminated) and (not Application.Terminated) do
    begin
      AktionenAusfuehren;
    end;
  except
    on E: EThreadExit do ; // nichts machen
    on E: Exception do
      Synchronize(HandleException);
  end;
end;

procedure TMyThread.AktionenAusfuehren;
begin
 // ...
  if ThreadAbbrechen then
    raise EThreadExit.Create;
 // ...
end;
  Mit Zitat antworten Zitat
Benutzerbild von OrallY
OrallY

Registriert seit: 29. Apr 2003
268 Beiträge
 
#6
  Alt 11. Mai 2003, 14:09
Danke! Deine Lösung gefällt gut! Doch hab ich das Problem jetzt so gelöst, dass ich in die Prozeduren, die aufgerufen werden, eine Abfrage eingebaut hab: sowas wie [b]if DoCancel then exit;[b].
Aber deine Lösung werde ich mir auf jedenfall merken .
.oO'rallY
Linux is like a tipi: no gates, no windows and a gnu-eating apache inside...
  Mit Zitat antworten Zitat
Benutzerbild von sakura
sakura

Registriert seit: 10. Jun 2002
Ort: Unterhaching
11.412 Beiträge
 
Delphi 12 Athens
 
#7
  Alt 11. Mai 2003, 14:17
Bitte nochmal für die langsameren unter uns. Warum kannst Du innerhalb des Threads nicht die Eigenschaft Terminated überprüfen? Wenn Du die Variable DoCancel testen kannst, müsste es mit der vorgesehenen Eigenschaft doch auch gehen. Andere Methoden könnten u.U. schneller zu Speicherleaks führen.

......
Daniel Lizbeth
Ich bin nicht zurück, ich tue nur so
  Mit Zitat antworten Zitat
Benutzerbild von OrallY
OrallY

Registriert seit: 29. Apr 2003
268 Beiträge
 
#8
  Alt 11. Mai 2003, 18:33
Bei der Prozedur handelte es sich um eine "Komprimierungsprozedur", d.h. eine Prozedur die mit ZLib arbeitete (oder besser, einem Nachfolger). Da die Prozedur erst wieder zurückkehrte, nachdem der Stream komprimiert war, wäre eine Terminated-Abfrage sinnlos gewesen. Wenn ich den Thread einfach mit TerminateThread gekillt habe, konnte diese Prozedur aber auch keinen Müll mehr beseitigen, es führte zu abstürtzen. Nun habe ich die ZLib CompresionStream mit einem Boolischen-Wert erweitert, der, wenn er auf true gesetzt wird, die Prozedur abbricht. Dies war möglich, da die Komprimierungsfunktion in einer schnuckeligen Schleife ablief. Also musste ich nach jedem Schleifendurchlauf nur die Variable überprüfen, die dazugefügt habe. Von außerhalb musste ich also nur noch die Variable auf true bzw. false setzten, um den Vorgang abzubrechen, ohne Speicherleaks zu riskieren.

Alles klar?
.oO'rallY
Linux is like a tipi: no gates, no windows and a gnu-eating apache inside...
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:42 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz