![]() |
Threadlogik Problem
Hallo,
ich steht grad auf dem Schlauch, ich hab ein kleines Logikproblem, bezüglich 2'er Threads... Der 1. Threads muß immer an sein, es sei denn der User klickt auf Stop... So eine Art WatcherThread... Der 2. Thread ich nenn Ihn mal WorkerThread, soll nur dann aktiv sein, wenn der 1. Thread etwas bestimmtes gefunden hat, dann soll der Workerthread etwas ausführen uns zwar nur einmal, und sich dann selber beenden. Das Problem ist, wenn ich das mal auf folgendes Szenario abbilde: 1. Thread findet ein bestimmtes Fenster, jetzt ruft er den 2. Thread auf, dieser sendet eine Nachricht, an das vom Thread 1 gefundene Fenster, jetzt muß ich ja irgendwie sicherstellen, das wenn die Nachricht versendet wurde, der 2. Thread sich beendet. Mir ist nur unklar woran ich das festmachen soll, weil ja der 1. Thread den 2. Thread created wenn das Fenster sichtbar ist. Das wäre ja dann ne art Endlosschleife? Was ich vermeiden muss irgendwie ohne den 1. Thread zu killen. Ich hoffe das mir jemand in mein Chaos folgen kann und einen Tip für mich hat... Viele Grüsse s! |
Re: Threadlogik Problem
Warum soll das eine Endlosschleife sein?
Vom Verlauf her sieht das doch so aus:
Code:
Wenn du beim WorkerThread FreeOnTerminate auf True setzt, dann gibt er sich ja selbstständig frei, wenn die Execute-Methode rum ist und er sich somit terminiert.
1. Thread läuft in einer (abbrechbaren) Endlosschleife und sucht ständig nach so einem Fenster
- - \/ 1. Thread findet ein Fenster, erstellt und startet einen WorkerThread - - \/ Der Worker-Thread arbeitet nicht in einer Endlosschleife, sondern sendet eine Nachricht (WM_??) an das Fenster und dann ist die Execute-Methode vorbei - - \/ 1. Thread bekommt, wenn benötigt, über das OnTerminate Ereignis mit, wenn der WorkerThread fertig ist Ist damit dein Problem geklärt, oder wohin solls genau gehen? Gruß alias5000 |
Re: Threadlogik Problem
Zitat:
Der 1. Thread muss ja unendlich nach einem Fenster suchen, wenn diese gefunden wird den Workerthread starten, dieser sendet die Nachricht und soll sich beendet wenn die Nachricht versendet wurde, was aber wenn das Fenster Fremdfenster nicht geschlossen wurde? Thread1 startet ja dann wieder Thread2? Genau das ist ja das Problem. Szenario 2 Thread1 findet das Fenster, Worker wird gestartet sendet die Nachricht und würde beendet werden, Fremdfenster wurde geschlossen. Fremdfenster wird erneut aufgerufen, also wieder alles von vorne! Das ist mir völlig unklar logiktechnisch... Ich zeigs mal per Code vielleicht wirds dann deutlicher:
Delphi-Quellcode:
Gruss
constructor TMozWatchDogThread.Create;
begin inherited create(true); freeOnTerminate := true; Priority := tpLowest; end; destructor TMozWatchDogThread.destroy; begin inherited destroy; end; procedure TMozWatchDogThread.Execute; begin while not(Terminated = true) do begin // Suche Fenster wenn handle > 0 dann // StarteWorkerThread; // hat workerthread nachricht gesendet und ist fremdfenster geschlossen, // dann alles von vorne, hat worker nachricht gesendet aber fenster noch offen // dann nicht erneut nachricht an fremdfenster senden! end; end; { TMozWatchDogWrokerThread } constructor TMozWatchDogWorkerThread.create; begin inherited create(true); freeOnTerminate := true; Priority := tpLowest; end; destructor TMozWatchDogWorkerThread.destroy; begin inherited destroy; end; procedure TMozWatchDogWorkerThread.Execute; begin // sende nachricht an fremdfenster, dann beende dich selber end; s! |
Re: Threadlogik Problem
Das ist dann eher eine Frage der Anwendungslogik.
Was genau soll sie machen und wie soll sie auf bestimmte Szenarien reagieren? Gerade Szenario 1 würde ich mir erstmal ohne eine konkrete Umsetzung überlegen, sondern erstmal, was das gewünschte Verhalten der Anwendung ist. Dann ist die Umsetzung einfacher. Beispiel: Wenn deine Mozilla-Software (liege ich richtig?) nicht geschlossen wird, trotz WM_CLOSE, oder was du sendest, dann musst du dir überlegen, wie du damit von der Anwendungslogik her umgehst. Soll eine MessageBox hochgehen, wenn die Anwendung nicht innerhalb von 10 Sekunden geschlossen wird,...? Sowas in die Richtung Gruß alias5000 |
Re: Threadlogik Problem
Nochmal anders erklärt, sagen wir der User öffnet in Mozilla den speichern dialog, worauf Thread 1 lauscht, sollte das der Fall sein soll Worker ne message in den Dialog von Moz posten, was auch passiert, nur kann ich den Dialog ja nicht killen, weil der User eventuell noch nen anderen Pfad wählen will oder sonstiges daher prüfen ob Handle des Dialogs > 0 ist
|
Re: Threadlogik Problem
Ja gut, aber im 1. Thread wirst du ja sehen, ob gerade ein Speicherndialog mit einem bestimmten Handle offen ist, oder nicht.
Du kannst dann ja einfach im 1. Thread ne Bool-Variable benutzen, die auf true gesetzt wird, wenn ein neues Fenster gefunden wurde und dazu ein Thread erstellt wurde. Der Workerthread verrichtet dann seine Arbeit und beendet sich. Solange die Boolean-Variable zu dem spezifischen Handle true ist, wird kein neuer Thread erstellt. Wenn dann der 1.Thread feststellt, dass das Handle dieses gefundenen Dialoges = 0 ist, setzt er die Bool-Variable zurück und würde somit später wieder einen Workerthread erstellen, wenn ein neuer Dialog geöffnet würde Verstanden, was ich meine? Gruß alias5000 |
Re: Threadlogik Problem
Theretisch ja, nur praktisch hat auch das nicht funktioniert, frag mich nicht warum, irgendwie beendet sich der worker ned :-(
|
Re: Threadlogik Problem
Code?
|
Re: Threadlogik Problem
Hi,
Zitat:
aber der WatchDogThread das Fenster immer wieder findet und immer neue WorkerThread startet? Das will wohl auch alias5000 mit dem Boolean verhindern. |
Re: Threadlogik Problem
Hi,
Wieso willst Du überhaupt nur um eine Nachricht zu senden, eine extra Thread starten ? Ich sehe da keinen Sinn drin, wenn der WatchThread sowieso erst wissen muss, ob das geklappt hat oder nicht, kann er's ja auch selber machen. Das vereinfach die Logik, macht das Programm schlanker und effizienter (ein extra Thread heißt ja auch extra Verwaltung) und dich glücklicher ;-) Gruss |
Re: Threadlogik Problem
Hm der code iss ja hier oben im Thread, der worker ist vom aufbau her identisch zum watcher...
Also alles in einem thread? Hmm ich hab doch 2 Threads genommen, weil ein Thread ja nicht beendet werden darf, also ned automatisch nur per Userwunsch, der andere ja, der soll nach einmaliger Ausführung beenden, ggf. wieder selber neustarten, wenn der Watcher es sagt. |
Re: Threadlogik Problem
Naja, kommt darauf an, was der Workerthread sonst noch so zu tun hat. Ich war jetzt davon ausgegangen, dass er nur diese eine Message sendet - so wie du es beschrieben hast.
Der Hauptthread könnte das ja locker machen anstatt einen Workerthread zu starten. Gruss |
Re: Threadlogik Problem
Vorschlag, ein Thread; Pseudocode:
Delphi-Quellcode:
Das wäre mein Vorschlag, kombiniert mit der Ein-Thread-Idee
TmeinThread = class(TThread)
... procedure Execute; override; ... end; implementation Procedure TmeinThread.Execute; var Handle: cardinal; b: boolean; begin b := false; repeat Handle := FindeDeinFenster; if Handle <> 0 then begin if not b then begin DialogSchließenMessageSenden; b := true; end; end else if (Handle = 0) and b then b := false; end; until self.Terminated end; Gruß alias5000 |
Re: Threadlogik Problem
Hi Alias, ich werds grad mal testen ob das so funktioniert, wie es sollte!
Erstmal herzlichen Dank! s! Ok, soweit schon mal Ok, Fenster wird gefunden, Nachricht wird versand. Aber, folgendes Problem was ich nun hab... Thread läuft (machs nun mit einem Thread), das Fenster wird aufgerufen, Nachricht wurde versand, der User schliesst das Fenster. Der User öffnet das Fenster erneut, Nachricht wird nicht erneut versand. :-( Das scheint das Logikproblem bei mir zu sein, wie nun erneut den Thread nach dem Fenster suchen lassen und wenn gefunden Nachricht senden, ohne den Thread vorher zu killen? Sowas wie ein Reset Ereignis, nach dem versenden der Nachricht. Ich poste mal den Code am besten, eventuell fällt sofort mein Fehler auf?
Delphi-Quellcode:
Pps. gibt es ggf. noch eine Möglichkeit zu verhindern, das der Thread 100% CPU schluckt?
constructor TIEWatcherThread.Create;
begin inherited Create(True); freeOnTerminate := True; Priority := tpLowest; end; destructor TIEWatcherThread.Destroy; begin inherited Destroy; end; procedure TIEWatcherThread.Execute; var wndMain, wndChild: HWND; begin b := False; while not (Terminated = True) do begin repeat wndMain := FindWindow('IEFrame', nil); if wndMain <> 0 then begin wndMain := FindWindow('#32770', 'Save Picture'); wndChild := FindWindowEx(wndMain, 0, 'ComboBoxEx32', nil); wndChild := FindWindowEx(wndChild, 0, 'ComboBox', nil); wndChild := FindWindowEx(wndChild, 0, 'Edit', nil); Handle := wndChild; if Handle <> 0 then begin if not b then begin GenerateRndGuidFilename; b := True; end; end else if (Handle = 0) and b then b := False; end; until Self.Terminated; end; end; procedure TIEWatcherThread.GenerateRndGuidFilename; var wndMain, wndChild: HWND; FPath, FFilename: array [0..255] of char; G: TGUID; S, FDelStr, FExt: string; begin MessageSend := False; repeat if Handle <> 0 then begin wndMain := FindWindow('IEFrame', nil); if wndMain > 0 then begin wndMain := FindWindow('#32770', 'Save Picture'); wndChild := FindWindowEx(wndMain, 0, 'ComboBoxEx32', nil); wndChild := FindWindowEx(wndChild, 0, 'ComboBox', nil); wndChild := FindWindowEx(wndChild, 0, 'Edit', nil); if not MessageSend then begin coCreateGuid(G); s := GuidToString(G); s := StringReplace(s, '-', '', [rfReplaceAll]); s := StringReplace(s, '{', '', [rfReplaceAll]); s := StringReplace(s, '}', '', [rfReplaceAll]); // get filename SendMessage(wndChild, WM_GETTEXT, SizeOf(FFilename), integer(@FFilename)); // extract extension FExt := ExtractFileExt(FFilename); s := s + FExt; // clear filename FDelStr := ''; StrPLCopy(@FFilename, FDelStr, SizeOf(FFilename)); SendMessage(wndChild, WM_SETTEXT, SizeOf(FFilename), integer(@FFilename)); // send random guid as filename + extension StrPLCopy(@FFilename, s, SizeOf(FFilename)); SendMessage(wndChild, WM_SETTEXT, SizeOf(FFilename), integer(@FFilename)); MessageSend := True; b := False; end; end else if (Handle = 0) and MessageSend then MessageSend := False; end; until Self.Terminated; end; |
Re: Threadlogik Problem
Zitat:
Zitat:
Delphi-Quellcode:
ist dein Helfer ;)
Sleep
|
Re: Threadlogik Problem
Hi,
mit der Message WM_SETTEXT wird das Fenster doch noch gar nicht geschlossen. Verstehe ich das richtig: Du setzt jetzt nur den Dateinamen ein, und erwartest jetzt, dass der Benutzer das Fenster schliesst ? Und wenn das so ist, dann solltest Du tatsächlich ein sleep(500) einbauen. Und. Wieso baust Du in diese Prozedur die gleiche Schleife ein wie im Hauptzweig der Execute ? Ist das nicht doppelt gemoppelt ? Und auch hier würde ich mindestens ein sleep(500) einbauen, sonst macht dem Benutzer das Arbeiten keinen Spass mehr. Gruss |
Re: Threadlogik Problem
Hmm ich bin jetzt einen anderen Weg als über die Threads gegangen klingt vielleicht wie: "Mit Kanonen auf Spatzen schiessen"
Aber ich hab dafür jetzt einen Hook geschrieben, das klappt wunderbar und ohne irgendwelche Probleme, wenn der User auf "OK" im Save Dialog klickt wird die GUID als Dateiname generiert und das File gespeichert und das geht nun ohne weiteres nicht wie im Thread mit endlos Generierung der GUID, wobei mit das Problem trotzdem mal interssiert hätte, wieso und warum :-) Trotzdem herzlichen Dank allen die so fleissig am helfen waren s! |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:38 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