Thema: Delphi Einem Thread Zeit geben

Einzelnen Beitrag anzeigen

xaromz

Registriert seit: 18. Mär 2005
1.682 Beiträge
 
Delphi 2006 Enterprise
 
#10

Re: Einem Thread Zeit geben

  Alt 9. Jun 2006, 12:47
Hallo,
Zitat von Olli:
Zitat von xaromz:
Mit dem Zugriff auf die Listenelemente hab ich kein Problem, der ist geschützt.
Wie? Ansonsten gälte u.U. das hier: Das was guste geschrieben hat, ist einerseits nicht so dumm, andererseits naiv. Das Problem ist, daß man jedem Listenelement eine eigene Critical Section mitgeben müßte. Tut man's nicht, hat man sogleich den Sinn des Thread ad absurdum geführt ...
Ich verwende eine CriticalSection, wenn ich die Liste irgendwo bearbeite. Das klappt auch so, wie es soll.
Zitat von Olli:
Zitat von xaromz:
Danke, ich spreche fließend x86er assembler .
Ich hoffe nicht, weil ich mich dann quasi blamiert habe - da steht ja aus Assemblersicht nur Nonsens, auch wenn die Opcodes selber existieren

Zitat von Olli:
Zitat von xaromz:
Wie gesagt, der Zugriff auf die Elemente ist gesichert.
Wie, wie, wie? Wenn du ein Ausschlußobjekt für eine riesige Liste hast, kann nur einer lesen oder schreiben, also serialisierst du den Zugriff wieder künstlich.
Natürlich muss ich den Zugriff irgendwie serialisieren. Da ich (s. o.) mit CriticalSection arbeite und damit sehr sparsam umgehe, serialisiere ich nur dort, wo es unumgänglich ist (Schreibzugriff auf Listenobjekte, Änderung der Liste). Ich ziehe also dem Arbeitsthread kein Listenelement unterm Arsch weg .
Zitat von Olli:
Zitat von xaromz:
Siehe oben.
Hat leider mit dem geschützten Zugriff nichts zu tun, wenn du auf die "Gleichzeitigkeit" der Threads wertlegst.
Wie gesagt, die Gleichzeitigkeit funktioniert prima.

Zitat von Olli:
Dann stellt sich mir aber die Frage, warum du die Liste immer neu befüllst anstatt den jeweiligen Eintrag zu ergänzen (oder zu ersetzen). Eine doppelt verlinkte Liste ermöglicht dir das einfache Einfügen oder Entfernen von Listenelementen ohne gleich die komplette Liste neu befüllen zu müssen ...
Nun, wenn in der Liste irgendwas drinsteht und der User einfach komplett andere Medien lädt, was bleibt mir anderes übrig, als den kompletten Listeninhalt zu ersetzen?
Zitat von Olli:
Zitat von xaromz:
Wenn ich das Programm beende, während der Thread noch läuft, erhält dieser keine Chance, sich sauber zu beenden. Deshalb möchte ich eben beim Beenden des Programms den Hauptthread kurz schlafen legen, damit der Arbeitsthread auf ein Flag reagieren und sich beenden kann.
und wie wacht der Hauptthread dann wieder von alleine auf? Dann wird dein Programm nämlich vermutlich zwangsbeendigt.
Sowas habe ich schon befürchtet.
Zitat von Olli:
Meines Erachtens ist deine Denk- und Herangehensweise zu naiv. Du könntest dir eine Menge Arbeit sparen, wenn jede Liste ein Ausschlußobjekt hat (könnte ein Byte- oder DWORD-Wert sein), der immer nur über die Interlocked-Funktionen bearbeitet wird. Dieses Ausschlußobjekt ist kein echtes Objekt sondern ein Referenzzähler. Da jedes Objekt nun nur noch ein Pointer auf einen Speicherbereich ist, übergibst du dieses an einen Thread nachdem der Aufrufer den Referenzzähler um 1 erhöht hat. Danach kann der Thread erstmal machen was er will, außer daß er davon ausgehen muß, daß die Daten jederzeit von einem anderen Thread gelesen werden können - die Integrität muß also garantiert sein (z.B. kritischer Abschnitt für jede der zu schreibenden Informationen ...). Wenn der (Arbeits-)Thread mit der Abarbeitung fertig ist, legt er sich erstmal selber schlafen (suspend) nachdem er den Referenzzähler um 1 reduziert hat. Dadurch ist er immer an einer wohldefinierten Stelle eingeschlafen. Will der Dispatcher-Thread nun dem Arbeits-Thread sagen, daß er wieder was machen soll, wird der Pointer (globale Variable o.ä.) zum Listeneintrag atomisch ausgetauscht und der Arbeits-Thread wieder aufgeweckt, womit die Schleife im Arbeits-Thread ihre Arbeit weiterführt. Damit ist zwar ein extra Thread (der Dispatcher) nötig, aber die Anzahl der Arbeits-Threads kann ohne Mühe variiert werden. Außerdem mußt du nur einen Listeneintrag in der Listbox aktualisieren, nicht die komplette Liste.
Ist zwar rührend, wie Du Dich um meine Threads kümmerst, aber das ist ja nicht mein Problem . Normalerweise funktioniert das prächtig.
Egal, wie ich den Zugrif steuere (Criticl Section, Interlock-Referenzzähler, Semaphore...), wenn ein Thread läuft, während ich das Programm beende, dann läuft er erstmal weiter und wird dann vermutlich einfach "abgeschossen".

Aber ich hab' das gerade so gelöst:
- Falls beim Beenden ein Thread läuft, signalisiere ich dem Thread ein Terminate und rufe WaitFor auf
- Anschließend werte ich das Flag im Thread aus und setze FreeOnTerminate aus False, damit das Handle in WaitFor erhalten bleibt und keine AV kommt
- Sobald WaitFor zurückgekehrt ist, zerstöre ich den Thread mit Free
Zitat von Olli:
Du kannst aber nur Windows sagen, daß dein aktueller Thread seine Rechenzeit abgibt ... an wen, läßt sich der Scheduler von einem Usermode-Programm sicher nicht vorschreiben ... selbst im Kernelmode geht das nur beschränkt.
Sowas hab' ich mir schon gedacht.

Aber mein Problem ist ja jetzt gelöst.

Gruß
xaromz
  Mit Zitat antworten Zitat