![]() |
[solved]Thread terminated nicht, obwohl OnTerminate
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo zusammen,
ich habe ein Problem, das sich für mich als ziemlich undurchsichtig erweist: Ich habe einen Thread erstellt, der ein externes Programm startet und auf dessen Beendigung wartet. Danach soll sich der Thread beenden Allerdings terminiert der Thread nicht, auch wenn die im OnTerminate zugewiesene "Aktion" abgearbeitet ist.
Delphi-Quellcode:
[gekürzt]
type TDemuxThread = class(TThread)
private FMPGFileContainer : TMPGFileContainer; protected procedure Execute; override; public constructor Create; property Terminated; property MPGFileContainer: TMPGFileContainer read FMPGFileContainer write FMPGFileContainer; end; ... constructor TDemuxThread.Create; begin inherited Create(true); FMPGFileContainer := nil; end;
Delphi-Quellcode:
Was im Execute steht, ist völlig unerheblich für mein Problem, ändert nichts daran. Egal ob alles im Execute steht oder gar nichts, das Problem bleibt bestehen (warum auch nicht :wall: )
procedure TDemuxThread.Execute;
begin if Assigned(FMPGFileContainer) then begin FMPGFileContainer.Files.Items[DemuxIndex].Demux; // MessageDlg('Blubb', mtError, mbYesNo, 0); //-> auskommentiert wegen Antwort 2 end; end; Dieses FMPGFileContainer.Files.Items[DemuxIndex].Demux; öffnet im Grunde per ShellExecAndWait ein externes Programm (DGIndex.exe) und wartet per WaitForSingleObject auf dessen Ende. Die MessaegBox Blubb poppt ohne Probleme auf Der Aufruf sieht folgendermaßen aus:
Delphi-Quellcode:
und die DemuxTerminate sieht so aus [gekürzt]:
procedure TfMain.btInputDemuxSelClick(Sender: TObject);
begin if not Assigned(DemuxThread) then begin DemuxThread := TDemuxThread.Create; DemuxThread.MPGFileContainer := MFC; DemuxThread.OnTerminate := DemuxTerminate; DemuxThread.Resume; end; end;
Delphi-Quellcode:
Auch diese MessageBox 'wir sind im onTerminate' poppt auf.
procedure TFMain.DemuxTerminate(Sender:TObject);
begin // MessageDlg('wir sind im OnTerminate',mterror,mbyesno,0);//-> auskommentiert wegen Antwort 2 end; Im CloseQuery schaue ich nach, ob der Thread terminiert ist, denn nur dann darf ich das Programm schließen
Delphi-Quellcode:
procedure TfMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin canclose := true; if not DemuxThread.Terminated then canclose := false; end; Und genau dort hänge ich immer fest. Die Aktion im OnTerminate wurde ausgeführt, alo müsste der Thread doch jetzt terminated sein, oder nicht? Warum also zm Kuckuck kann ich das Programm nicht schließen gekürzter Quelltext heißt: Es steht noch mehr drin, das habe ich aber alles bei mir schon auskommentiert und hier aus Übersichtlichkeit weggelassen Nochmal zusammenfassend: Alles im Thread.Execute wird ohne Probleme ausgeführt. Aiuch die Anweisungen im Thread.OnTerminate (=DemuxTerminate) werden ausgeführt Aber mein Thread terminiert danach nicht. Warum? p.s. ab und zu sieht die 'Blubb' MessageDlg verkrüppelt aus, so wie im Bild, hat das etwas mit dem Problem zu tun? [edit] MessageBoxen auskommentiert wegen Antwort 2, jedoch ohne Nutzen [/edit] |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Ähm, mal sone grundsätzliche Frage...du benutzt doch überall Messageboxen. Soweit ich weiß darf in einem Thread doch kein VCL Zeug aufgerufen werden ohne TThread.Synchronize zu verwenden, weil das irgendwie die Threadausführung durcheinander wirft. Versuch doch mal, das programm durchlaufen zu lassen, wenn du alle Messageboxen auskommentiert hast.
Mfg, Alleinherrscher |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Zitat:
Nützt aber nix, kann das Programm trotzdem nur noch per TaskManager abschiessen. |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Nochwas, was ich nicht ganz verstehe...
Delphi-Quellcode:
Warum schreibst du rein "property Terminated"? Überschreibt das nicht die ursprüngliche Terminated propertry, weshalb sich der Wert nicht mehr ändern, wenn der Thread tatsächlich beendet ist??? Was passiert wenn du die Zeile ebenfalls weglässt?
type TDemuxThread = class(TThread)
private FMPGFileContainer : TMPGFileContainer; protected procedure Execute; override; public constructor Create; property Terminated; property MPGFileContainer: TMPGFileContainer read FMPGFileContainer write FMPGFileContainer; end; By the way? Analysis II? Mathe oder Physikstudent? ;-) |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Benutz statt MessageDlg einfach
![]() Ansonsten entfern das "property Terminated;". Sollte dann so funktionieren wie Du es Dir vorstellst. |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Zitat:
[Pascal Error] uMain.pas(197): E2362 Cannot access protected symbol TThread.Terminated Ich dachte, durch das (erneute) Aufnehmen mache ich die Property public und kann so darauf zugreifen [OT] @alleinherrscher: Beinahe: Ingenieurinformatik. Hat aber eigentlich absolut nix mit der Datei Analysis II zu tun denn bei diesen Dateien handelt es sich um MPG Dateien (=Aufnahmen auf dem Fernsehen) (hier eben das nostalgische Telekolleg Mathematik) [/OT] |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Okay, das stimmt natürlich, Terminate ist eine private property... Du könntest im Hauptprogramm "TThread.OnTermiante" verwenden, um eine boolsche variable zu setzten die du in CloseQuery abfragst.
Man kann bestimmt auch dafür sorgen, dass Terminated "public" wird, aber dafür muss man das etwas anders machen... (grade überlegt wie das geht) Mfg |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Hmm, stimmt Terminated ist Private. Naja, prinzipiell könntest Du halt WaitFor nutzen. Also sowas in der Art:
Delphi-Quellcode:
procedure TfMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin // Wenn DemuxThread existiert, warten wir bis der Thread nicht länger ausgeführt wird if Assigned(DemuxThread) then DemuxThread.WaitFor; end; |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Zitat:
Zitat:
Zitat:
Zusammenfasssend: :dp: |
Re: Thread terminated nicht, obwohl OnTerminate aufgerufen
Also:
1. MyThread.FreeOnTerminate := False; 2. Spendiere dem Thread eine 'Public Property Done : Boolean' 3. Im TMyThread.Create: 'Done := False' 4. Letzte Zeile der 'Execute-Methode' : 'Done := True' 5. Nun kannst Du vom Haupthtread prüfen, ob der Thread fertig ist. 6. Freigeben des Threads nicht vergessen. P.S.: Die Eigenschaft 'Terminated' dient als Signal von außen. Du musst in der Execute-Methode diese Eigenschaft prüfen, wenn Du den Thread beenden möchtest. Die Eigenschaft wird NICHT gesetzt, wenn der Thread fertig ist. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz