AGB  ·  Datenschutz  ·  Impressum  







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

Thread in DLL suspendieren

Ein Thema von Blubbels · begonnen am 15. Jan 2009 · letzter Beitrag vom 30. Jan 2009
Antwort Antwort
Blubbels

Registriert seit: 21. Okt 2008
8 Beiträge
 
#1

Thread in DLL suspendieren

  Alt 15. Jan 2009, 21:12
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:
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;
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.
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
  Mit Zitat antworten Zitat
Blubbels

Registriert seit: 21. Okt 2008
8 Beiträge
 
#2

Re: Thread in DLL suspendieren

  Alt 30. Jan 2009, 08:04
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.
  Mit Zitat antworten Zitat
DMW

Registriert seit: 6. Sep 2006
Ort: Münster
269 Beiträge
 
Delphi XE Professional
 
#3

Re: Thread in DLL suspendieren

  Alt 30. Jan 2009, 08:18
MSDN zu SuspendThread():
Zitat von MSDN:
This function is primarily designed for use by debuggers. It is not intended to be used for thread synchronization. Calling SuspendThread on a thread that owns a synchronization object, such as a mutex or critical section, can lead to a deadlock if the calling thread tries to obtain a synchronization object owned by a suspended thread. To avoid this situation, a thread within an application that is not a debugger should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately.
Moritz
"Hey, it compiles! Ship it!"
C++Builder Pages
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Thread in DLL suspendieren

  Alt 30. Jan 2009, 08:24
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?
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Blubbels

Registriert seit: 21. Okt 2008
8 Beiträge
 
#5

Re: Thread in DLL suspendieren

  Alt 30. Jan 2009, 08:58
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:
should signal the other thread to suspend itself. The target thread must be designed to watch for this signal and respond appropriately.
Auch das habe ich eigentlich umgesetzt, indem ich das Betreten und Verlassen der Critical Section mit einem Event kombiniere, auf den ich vor dem Pausieren warte und es nach Timeout gar skippe:

Delphi-Quellcode:
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;
IsInThreadCritical ist halt im Code im ersten Post als Abbruchbedingung noch hinzugefügt.
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?
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: Thread in DLL suspendieren

  Alt 30. Jan 2009, 09:10
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.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Blubbels

Registriert seit: 21. Okt 2008
8 Beiträge
 
#7

Re: Thread in DLL suspendieren

  Alt 30. Jan 2009, 12:40
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

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
  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 05:39 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