![]() |
Thread blockiert beim zweiten Aufruf von Synchronize
Hallo,
folgender Code blockiert beim zweiten Aufruf/Durchlauf von Synchronize
Delphi-Quellcode:
Ich hatte vorher diese Funktionen ohne Problem mit Sleep und ohne Timer genutzt, aber seit dem ich den Aufruf über den Timer mache bleibt es nach dem zweiten Durchlauf hängen. Seht ihr woran das liegen könnte?
procedure TWorkerThread.SyncGetNewEntries;
begin if Assigned(OnGetNewEntries) then OnGetNewEntries(fWorkList); end; procedure TWorkerThread.OnMainTimer(Sender: TObject); begin fMainTimer.Enabled := False; if fTriesIt < 3 then begin if not StartWork(False, 3, False) then begin Inc(fTriesIt); fMainTimer.Interval := 60000; end else begin fTriesIt := 0; Synchronize(SyncGetNewEntries); //Erster Aufruf holt noch die Daten //beim zweiten Timerdurchlauf bleibt er an der Stelle ohne einen Fehler hängen/Programm //reagiert nicht mehr - wie bei einem Deadlock fMainTimer.Interval := 1000; end; if not fClosingTime then fMainTimer.Enabled := True; end; end; procedure TWorkerThread.Execute; var i : Integer; msg : tagMSG; begin fWorkList := TSLWorklist.Create; fHTTP := TIdHTTP.Create(nil); fMainTimer := TTimer.Create(nil); try fClosingTime := False; fMainTimer.Enabled := False; fMainTimer.Interval := 1000; fMainTimer.OnTimer := Self.OnMainTimer; fWaitMS := 5000; fHTTP.HTTPOptions := [{hoForceEncodeParams}]; fMainTimer.Enabled := True; while GetMessage(msg, 0, 0, 0) do DispatchMessage(Msg); fClosingTime := True; fMainTimer.Enabled := False; if (fTriesIt < 3) and (fWorkList.Count > 0) then begin for i := 0 to fWorkList.Count - 1 do fWorkList.Items[i].ExecuteAfter := Now; StartWork(False, 1, True); end; finally fWorkList.Clear; FreeAndNil(fMainTimer); FreeAndNil(fHTTP); FreeAndNil(fWorkList); end; end; Zusatz: Der bleibt an der folgende Stelle in der Funktion TThread.Synchronize der Unit Classes hängen:
Delphi-Quellcode:
Scheint irgendwie ein Deadlock eingetreten zu sein. Wie kann ich vorgehen, um das Problem zu lösen?
{$IFDEF MSWINDOWS}
begin LeaveCriticalSection(ThreadLock); try WaitForSingleObject(SyncProcPtr.Signal, INFINITE); //hier wartet die Funktion ewig finally EnterCriticalSection(ThreadLock); end; end; {$ENDIF} |
Re: Thread blockiert beim zweiten Aufruf von Synchronize
ich versteh die verwendung deines timers nicht. brauchst du den unbedingt? ich kenne den kontext deines programms nicht wirklich.
was genau macht diese zeile, denn da wird wahrscheinlich der fehler stecken, bzw was genau ist dein code bei OnGetNewEntries.
Delphi-Quellcode:
nutzt die critical sections, die du nicht mehr verlässt?
if Assigned(OnGetNewEntries) then OnGetNewEntries(fWorkList);
|
Re: Thread blockiert beim zweiten Aufruf von Synchronize
Wie schon gesagt, hatte ich das vorher ohne Messageschleife und Timer gelöst, dafür aber mit Sleep(xy). Das Problem ist, dass bei einem Fehler (bei der Übermittlung der Daten im Thread an eine Webseite) die Zeit bis zum nächsten Versuch von von einer Sekunde auf 60 Sekunden geändert werden soll. Wenn ich das mit sleep(60000) mache und ich in der Zeit das Programm beenden möchte musste ich immer warten bis sleep() fertig war. Deshalb dachte ich mir, ich mach das jetzt mit einem Timer.
Delphi-Quellcode:
OnGetNewEntries ist ein Ereignis, welches die Elternklasse aufruft neue Werte zu übergeben und mehr passiert da auch nicht. fWorklist ist ein array of record.
if Assigned(OnGetNewEntries) then OnGetNewEntries(fWorkList);
Critical Sections nutze ich selber nicht, dafür aber die Komponente idThread in einer anderen Unit im Programm (diese benutzt ja meines Wissens CriticalSections). Wie gesagt, es hat alles mit dem Code funktioniert - das einzige, was ich geändert habe ist der Aufruf über den Timer und die Messageloop. EDIT: Ops .... "fWorklist ist ein array of record." ist falsch. fWorklist ist ne Klasse. |
Re: Thread blockiert beim zweiten Aufruf von Synchronize
Ich würde das Konzept umstellen:
1. Thread in Execute läuft mit while not Terminated 2. Intern mit TEvent warten auf: A) Wurde TEvent ausgelößt -> Thread soll sich beenden B) Auf den TimeOut -> jetzt hat dein Timer sozusagen zugeschlagen 3. Nach der Fallunterscheidung von dem Warten entsprechend Reagieren A) Thread sicher zum "Ende" führen B) Deine OnTimer-Methode hier aufrufen. Hier wird auch die nächste WarteZeit (TimeOut) für den nächsten Durchgang gesetzt. Ich hoffe, das hilft dir. Gruß, Chris |
Re: Thread blockiert beim zweiten Aufruf von Synchronize
Einen schnellen Erfolg hab ich gerade mit der
![]() Chris, meinst du dass so das Synchronize Problem behoben wird? Hmmm ... ausprobieren werde ich es auf alle Fälle mal. |
Re: Thread blockiert beim zweiten Aufruf von Synchronize
Zitat:
Ich würde es zumindest mal in dieser Richtung probieren und schauen was passiert :-) Gruß, Chris |
Re: Thread blockiert beim zweiten Aufruf von Synchronize
Natürlich darf jeder Thread eine Nachrichtenschleife haben.
Der Punkt, an dem der Thread hängt, ist der normale Punkt, an dem ein Thread auf den Hauptthread wartet. Anscheinend kommt dein Hauptthread nicht mehr dazu, Application.Idle aufzurufen. Macht der Hauptthread irgendetwas besonderes, wenn der Arbeiterthread hängt? |
Re: Thread blockiert beim zweiten Aufruf von Synchronize
Ich hab das Gefühl der Messageloop + Syncronize nicht klappt. Wenn ich nicht ganz falsch liege arbeitet synronize intern auch mit Messages. Vielleicht geht da etwas scheif wenn der Messageloop schon was abholt.
|
Re: Thread blockiert beim zweiten Aufruf von Synchronize
Nachrichtenschleifen zweier Threads sind vollkommen unabhängig. Außerdem arbeitet Synchronize nicht mit Fensternachrichten, sondern mit einer gelockten Liste.
|
Re: Thread blockiert beim zweiten Aufruf von Synchronize
Zitat:
Event setzen, WM_Null-Message an Application.Handle schicken und Medthode an Liste anhängen (in umgekehrter Reihenfolge). |
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:04 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