![]() |
Thread in DLL suspendieren
Hallöchen,
Ich hätte da mal ne Frage zu Threads und DLLs... Nehmen wir mal MeinThread vom Typ TThread, der ordentlich was zu tun hat. Direkt in eine Anwendung eingebunden läuft alles sauber durch, MeinThread.Suspend und MeinThread.Resume klappen, MeinThread.Terminate klappt einwandfrei etc. Nun eine DLL drumgekapselt, mit ein paar Exports um eben den Thread zu starten, stoppen, oder pausieren. Hier der kritische Punkt:
Delphi-Quellcode:
Das Problem nun: der Thread pausiert einfach nicht! Starten und Anhalten klappt dagegen einwandfrei. Per Debugger in Suspend reingeschaut zeigt, daß das darin aufgerufene SuspendThread mit Erfolg aufgerufen wird.
function MeinThreadPause(): integer; stdcall;
begin Result := -1; if not Assigned(MeinThread) then begin Result := -7; end; if MeinThread.Suspended then begin MeinThread.Resume; Result := 1; end else begin MeinThread.Suspend; Result := 0; end; end; Ein weiterer Aufruf von MeinThreadPause (zum resumen gedacht) erkannt dann halt Suspended, aber Resume (das ResumeThread darin) schlägt fehl. Daß Synchronize in DLLs nicht klappt, ist mir bewusst, der Thread auch dementsprechend mit ner TCriticalSection abgesichert und getestet. Ob/was man dem Thread antun muss, damit Suspend/Resume laufen, weiß ich leider nicht und hab auch via Google & co. nichts gefunden. Wäre für Tipps dankbar :) |
Re: Thread in DLL suspendieren
Hmm... kann doch nicht sein, daß ich der einzige bin, der Threads in einer DLL verwendet ;)
Ich bin der Sache ein gutes Stück näher gekommen, indem ich einem versteckt vom Thread aufgerufenen anderen Thread gefunden habe, in dem noch Synchronize verwendet wurde. Jetzt hänge ich ein Stück weiter noch fest: jedes 7. bis 13. mal hängt das Pausieren auf obige Methode das ganze Programm auf. Was mir inzwischen aufgefallen ist: OnTerminate etwa wird threadintern auch mit Synchronize gekapselt und ist daher in einer DLL nicht einsetzbar. Gibt es evtl. noch andere derartige "versteckte" Fälle? Resume und Suspend zumindest scheinbar schonmal nicht, die wenden ja wirklich nur die API-Aufrufe an. |
Re: Thread in DLL suspendieren
![]() Zitat:
|
Re: Thread in DLL suspendieren
Ein Thread von außen pausieren zu lassen ist schonmal nicht die feine englische Art. Du darfst dann nicht auf threadinterne Variablen zugreifen. Gehört aber nicht zu deinem primären Problem. Könnte aber eine Erklärung sein, dass keiner hier etwas sagen kann. Es benutzt eher keiner.
Was machst du denn in dem Thread? Hast du mal einen Thread getestet, der aus einer Endlosschleife nix macht? |
Re: Thread in DLL suspendieren
Ihr seid beide schonmal virtuelles Gold wert, danke :)
@DMW: Ja das hatte ich auch schon gelesen ;) Und mehrfach drüber gegrübelt, zugegeben! Primärzweck ist nicht Debuggen, sondern Userkomfort (rechenintensiven Vorgang pausieren), aber der Begriff Primärzweck sagt ja noch nicht aus, daß das die einzige Nutzung sein darf. "It is not intended to be used for thread synchronization." ist auch klar. Benutze ich auch nicht dafür :) - synchronisieren tue ich über critical sections. Hinauslaufen tut das dann vermutlich auf: Zitat:
Delphi-Quellcode:
IsInThreadCritical ist halt im Code im ersten Post als Abbruchbedingung noch hinzugefügt.
procedure ThreadEnterCritical;
begin CritialThreadEvent.ResetEvent; CritialThreadSection.Enter; end; procedure ThreadLeaveCritical; begin CritialThreadSection.Leave; CritialThreadEvent.SetEvent; end; function IsInThreadCritical(const TimeOut: cardinal): boolean; begin Result := (CritialThreadEvent.WaitFor(TimeOut)=wrTimeout); end; Hmmm... mache ich da gerade etwas dummes fällt mir so auf, brauche ich evtl. eine zweite TEvent-Instanz für den Event, um in IsInThreadCritical von außen zu prüfen? Könnte ich das sonst irgendwie besser machen, hab ich die MSDN-Empfehlung da falsch verstanden? Genau genommen steht da ja drin, dem Thread selber zu signalisieren, davor hatte ich etwas zurückgeschreckt, weil mich schon das ewige "if not Terminated" ziemlich annervt und ich es für unschön empfinde ;) @sirius: auf threadinterne Variablen greif ich von außen eh nicht zu, genausowenig wie auf threadöffentliche ;) Die sind tabu, solange der Thread nicht terminiert ist, ganz klar, da gibt es nur einseitige Kommunikation, nämlich Ereignisse (Synchronize/CriticalSection). Direkt eingebunden ist das ja auch alles sauber genug, um sich nicht eben so aufzuhängen. Der Thread verarbeitet größere Dateien, Kein Netzwerk, keine Datenbank, kein COM (hmmm das könnte ich nochmal genauer prüfen!) oder sonstwas spektakuläres, aber immerhin soviel Code, daß ich nach einem genervten Tag der Suche erstmal wieder hier fragen wolte, ob ich was generelles übersehe ;) Die kleine Endlosschleife klappt übrigens problemlos, ja, das hatte ich schon getestet :| Auch Dir ein Danke für den Hinweis bzgl. des Pausierens von außerhalb. Wie oben geschrieben hatte ich eigentlich gedacht ich hätte das mit dem Event abgedeckt, aber sollte mir dann wohl noch ein echtes internes Pausesystem überlegen? |
Re: Thread in DLL suspendieren
Zum Anhalten einfach in eine Wartefunktion mit waitforsingleobject o.ä. rennen lassen (was du anscheinend mit CritialThreadSection schon implementiert hast).
Die Dateiarbeit könnte aber auch die Ursache sein, warum suspendthread nicht funktioniert. Denn das klappt IMHO nur im UserMode-Code. Gewisse Dateifunktionen switchen aber in den Kernel-Mode. Und das könnte u.U. eine weile dauern. In der Zeit bewirkt suspend evtl. nichts. |
Re: Thread in DLL suspendieren
Hätte ich ja jetzt eher nicht vermutet, weil das Pausieren ja klappt, wenn der Thread direkt in die Anwendung eingebunden ist (mit Zuckungen im Zeigefinger hundertfach getestet ;) ), aber da war vielleicht was dran :shock:
Das TEvent.WaitFor hat nur ein WaitForSingleObject verwendet (schon absichtlich nicht CoWaitForMultipleHandles wie in neueren Delphi-Versionen eigentlich Standard, sondern gepatchte SyncObjs um auch unter 95 zu laufen) - aber nachdem ich dann den Unterschied zu WaitForSingleObjectEx gelesen und dort auch ReadFileEx/WriteFileEx mti queued I/O erwähnt gesehen habe, bin ich darauf umgestiegen. Erstes Testen war positiv :) Super, dankeschön :thumb: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 03:32 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