Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   WaitForMultipleObjects erkennt Beendigung von Threads nicht (https://www.delphipraxis.net/166437-waitformultipleobjects-erkennt-beendigung-von-threads-nicht.html)

Pussyranger 13. Feb 2012 19:24

WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Hallo, ich bins mal wieder! :-D

Ich erstelle unterschiedlich viele Threads, auf deren Beendigung das Programm warten soll. Bisher hab ich immer über das OnTerminate-Ereignis der Threads die Anzahl der Threads runtergezählt und mit
Delphi-Quellcode:
while ThreadAnzahl > 0 do
begin
  Sleep(1);
  Application.ProcessMessages;
end;
auf die Threads gewartet. Nun ist das natürlich höchst unschön und ich denke, dass es mit WaitForMultipleObjects effizienter wäre.
Leider kapiert WaitForMultipleObjects aber nie, dass die Threads beendet wurden :(

Hier die Prozedur, in der die Threads erzeugt werden:
Delphi-Quellcode:
function Unterschiede_markieren(Bild1, Bild2: TBitmap; Blend: Real; Toleranz: Byte):TBitmap;
VAR i,j,Breite,Hoehe,Itert:integer; B1,B2: ColorArray; SysInfo: TSystemInfo; HandleArray: array of THandle;
begin
  GetSystemInfo(SysInfo);
  ThreadCount:=SysInfo.dwNumberOfProcessors;
  SetLength(Thread, ThreadCount);
  SetLength(HandleArray, Threadcount);

  result:=TBitmap.Create;
  if NOT Assigned(fertig_Bild) then fertig_Bild:=TBitmap.Create;
  fertig_Bild.Width:=Bild2.Width;
  fertig_Bild.Height:=Bild2.Height;

  for i := 0 to ThreadCount-1 do
  begin
    Thread[i]:=TDifference_Finder.Create(Bild1, Bild2, Round(i*Bild2.Height/ThreadCount), Round((i+1)*(Bild2.Height-1)/ThreadCount), Blend, Toleranz, true);
    HandleArray[i]:=Thread[i].Handle;
    Thread[i].FreeOnTerminate:=true;
    Thread[i].Resume;
  end;

  WaitForMultipleObjects(Length(HandleArray), @HandleArray[0] ,true, INFINITE);

  result.Assign(fertig_Bild);
end;
LG,

Pussyranger

BUG 13. Feb 2012 20:07

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
EDIT: Rufst du in den Threads synchronize oder ähnliches auf? Das könnte einen netten Deadlock geben.

[EDIT]Vermutlich Blödsinn: [/EDIT]
Könnte es sein, dass ein Thread schon fertig ist, wenn WaitForMultipleObjects aufgerufen wird?
Wie sich WaitForMultipleObjects dann verhält, habe ich nicht gefunden. Rufe mal am Ende des Threads ein
Delphi-Quellcode:
sleep(1000);
(bzw. einen Zeitraum, indem das Warten auf jeden Fall ausgelöst wird) auf und gucke, ob das dass Problem behebt.

Sir Rufo 13. Feb 2012 21:26

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Irgendwie ja schon komisch ... da wird die Berechnung in den Hintergrund geschickt und im Vordergrund wird der Thread schlafen gelegt ... irgendwie hatte ich das mit den Threads anders in Erinnerung ...

Ab in den Hintergrund und wenn alle fertig sind - Reaktion auf das OnTerminate-Event - dann die Ergebnisse zusammentragen und ausgeben.

x000x 14. Feb 2012 01:26

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Moin moin,

hast du geprüft, ob wirklich alle Threads beendet sind?

Sir Rufo 14. Feb 2012 03:30

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Eventuell gibt es aber auch eine Zugriffsverletzung in den Threads, da ja die Threads auf die gleichen Objekte zugreifen (Bild1, Bild2) ... und sogar noch auf fertig_bild!

TBitmap ist nicht threadsicher ... das hatten wir doch schon ;)

Pussyranger 16. Feb 2012 13:32

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Delphi-Quellcode:
Sleep(1000);
bewirkt nichts.
Da alle Threads zumindest das OnTerminate-Ereignis auslösen, nehme ich an, dass die Threads dann auch beendet werden.
Eine Zugriffsverletzung gibt es denke ich nicht, denn bisher hat ja alles wunderbar funktioniert. Die Threads werden synchronisiert, bevor auf fertig_Bild zugegriffen wird.

BUG 16. Feb 2012 13:47

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Zitat:

Zitat von Pussyranger (Beitrag 1151422)
Die Threads werden synchronisiert, bevor auf fertig_Bild zugegriffen wird.

So wie ich synchronize verstanden habe, wartet es, bis der Main-Thread wieder im Messageloop ist, um dann sicher die übergebene Prozedur ausführen zu können.
Dein Main-Tread wartet allerdings auf deine Arbeitsthreads.
:arrow: Klassischer Deadlock.

Pussyranger 16. Feb 2012 15:44

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Am Synchronize hats gelegen! Allerdings muss ich ja irgendwie die Teilbilder zusammenfügen.
Übers OnTerminate-Ereignis geht es nicht, da das auch zu einem DeadLock führen würde.
Nun habe ich die Deklaration für die Teilbilder in den public-Bereich geschrieben.
Wenn WaitForMultipleObjects beendet ist, rufe ich folgenden Code auf:
Delphi-Quellcode:
for i := 0 to ThreadCount-1 do
begin
  fertig_Bild.Canvas.Draw(0, Thread[i].StartYt, Thread[i].Finish);
  Thread[i].Finish.Free;
end;
Trotzdem wird der Speicher von Finish nicht wieder freigeben. Wieso?

Edit: FreeOnTerminate hab ich auf false gesetzt.

BUG 16. Feb 2012 16:14

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Zitat:

Zitat von Pussyranger (Beitrag 1151454)
Trotzdem wird der Speicher von Finish nicht wieder freigeben. Wieso?

Woran erkennst du denn, das der Speicher nicht freigegeben wird?
Die Zahl im Taskmanager muss auf solche Änderung nicht reagieren.

Pussyranger 16. Feb 2012 16:41

AW: WaitForMultipleObjects erkennt Beendigung von Threads nicht
 
Ich wollte die Prozedur 100 Mal hintereinander aufrufen. Dabei hat mir der Taskmanager für das Programm zwar immer maximal 800MB angezeigt, aber die Auslastung des RAM insgesamt ist kontinuierlich bis auf 100% gestiegen.


Alle Zeitangaben in WEZ +1. Es ist jetzt 11:06 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