Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Lesen einer außerhalb des Threads verwalteten Liste (https://www.delphipraxis.net/173839-lesen-einer-ausserhalb-des-threads-verwalteten-liste.html)

Der schöne Günther 20. Mär 2013 11:54

Lesen einer außerhalb des Threads verwalteten Liste
 
Situation:

Delphi-Quellcode:
TKlasse = class
   protected type meinThread = class(TThread)
      [...]
   end;
   private var kritischerAbschnitt: TCriticalSection;
   
   public var meineListe:TList<TDatensatz>;

   [...]
end;
Delphi-Quellcode:
TKlasse
hat einen
Delphi-Quellcode:
TThread
der öfter mal einen neuen
Delphi-Quellcode:
TDatensatz
an die Liste
Delphi-Quellcode:
meineListe
anhängt. Würde dieses Anhängen die Liste größer als ein bestimmtes Maximum werden lassen, wird der älteste Datensatz herausgeworfen.

Nun möchte ich allerdings auch im Hauptthread unkompliziert schauen, wieviele Datensätze ich schon habe, einen auswählen und auch grafisch darstellen. Problem: Niemand garantiert mir, dass ein ausgewählter Datensatz in der nächsten Zeitscheibe nicht schon durch den Nebenthread entfernt wurde!

Als Lösung fällt mir nur ein, den kritischen Abschnitt (an den sich natürlich beide Threads halten müssen) voll public zu machen um ihn dann auch im Hauptthread zu benutzen:
- Abschnitt betreten
- TDatensatz in der Liste finden
- Grafisch darstellen
- Abschnitt verlassen

Aber ganz ehrlich - Bei jedem möglichen Zugriff mit dem kritischen Abschnitt zu jonglieren ist doch einfach nur hässlich und fehleranfällig. Ich würde lieber einen Abend an der Stange tanzen gehen als den Zugriff auf "meinen" kritischen Abschnitt public nach außen zu führen. :oops:

Sind meine Bedenken unbegründet? Oder habe ich eine bessere Methode übersehen?

taveuni 20. Mär 2013 12:13

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Dann mach aus var meineListe ein property.
Und im Getter gibts Du Liste innerhalb der CritcalSection zurück.
Somit braucht der Hauptthread nichts von einer Criticalsection zu wissen.

Der schöne Günther 20. Mär 2013 12:21

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Richtig.

Aber das ändert nichts daran, dass
  • Liste holen
  • Durch Elelemte der Liste wandern
  • Element finden
  • Dinge mit dem Element tun
atomar ablaufen müssen.

Sonst passiert bsp. das hier:
  • Ich finde mein Element
  • Ich tue Dinge damit
  • Ich werde "unterbrochen" vom Nebenthread
  • Nebenthread entfernt das Element aus der Liste...
  • ... und ruft den Destruktor des Elements auf
  • will weiter Dinge tun

taveuni 20. Mär 2013 12:23

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Absolut korrekt. Das muss immer so sein wenn unterschiedliche Threads eine Liste lesen/schreiben.
Nur kannst Du die atomare Absicherung privat in der Klasse vornehmen.

BUG 20. Mär 2013 22:34

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Das alte Lied: Parallele Systeme sind schwer zu programmieren :wink:


Zitat:

Zitat von Der schöne Günther (Beitrag 1208059)
- Abschnitt betreten
- TDatensatz in der Liste finden
- Grafisch darstellen
- Abschnitt verlassen

Enthält der Datensatz Referenzen oder ist besonders groß? Wenn nicht, würde ich eine andere Vorgehensweise vorschlagen:
  • Abschnitt betreten
  • TDatensatz in der Liste finden
  • Abschnitt verlassen
  • Grafisch darstellen
Kritische Abschnitte sollten so klein wie möglich sein. Das Zeichnen dauert vermutlich sogar länger als eine typische Listenoperation.

Dies ließe sich noch verbessern:
Code:
datensatz = tKlassenObjekt.findeDatensatz(...);
stelleDar(datensatz);
Die CriticalSection und die Liste bleiben dabei privat und alles ist schön gekapselt.

Schöner wäre noch, wenn du für die Liste eine Klasse schreibst, die solche Funktionen wie findeDatensatz und einfuegeDatensatz threadsicher bereitstellt. Das sorgt dann dafür, dass du dich im Hauptthread sowie im andere Thread nicht mehr um die Threadsicherheit kümmern musst.

Wenn die Datensätze zu groß oder zu kompliziert zum Kopieren sind, dann könntest du mit Referenzzählung arbeiten.
Das sollte natürlich auch alles threadsafe und deadlockfrei passieren :mrgreen:

Der schöne Günther 21. Mär 2013 07:15

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Zitat:

Zitat von BUG (Beitrag 1208136)
Das alte Lied: Parallele Systeme sind schwer zu programmieren

Ja ich merke auch langsam, dass ich nicht der erste Mensch auf Erden bin, der sich damit herumärgert :-D

Zitat:

Zitat von BUG (Beitrag 1208136)
Enthält der Datensatz Referenzen oder ist besonders groß?

Das steht noch nicht ganz fest, möglicherweise wird er alles andere als klein weshalb ich bislang davon ausgegangen bin, dass das Zeichnen sogar schneller als ein Kopiervorgang über die Bühne geht. Aber wahrscheinlich liege ich damit falsch.

Zitat:

Zitat von BUG (Beitrag 1208136)
Schöner wäre noch, wenn du für die Liste eine Klasse schreibst, die solche Funktionen wie findeDatensatz und einfuegeDatensatz threadsicher bereitstellt. Das sorgt dann dafür, dass du dich im Hauptthread sowie im andere Thread nicht mehr um die Threadsicherheit kümmern musst.

Das wäre die beste aller Welten. Nur wird es am Ende wahrscheinlich wieder auf ein Dutzend verschiedene Kriterien, einen Datensatz zu "finden" hinauslaufen, was dann wieder auf eine Menge Methoden hinausläuft...


Vielen Dank für die Antworten bislang!:thumb:

Sir Rufo 21. Mär 2013 07:37

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Du solltest den Thread wie einen Freund behandeln.

Du gibst diesem Freund ein paar Äpfel zum Essen.

Es ist unhöflich bei jedem Passanten, der vorbeikommt, dem Freund die Äpfel aus den Händen zu reißen, nur um diesem Passanten die Äpfel zu zeigen.

Frage den Freund, dass er dir die Äpfel zeigen soll (er wird beim Essen unterbrochen), oder vereinbare mit ihm, dass er dir Rückmeldungen geben soll, welchen Apfel er gerade isst, wie viel er von dem Apfel schon gegessen hat und wenn der Apfel gegessen ist (er kann fast kontinuierlich essen).

Thread-Programmierung hat also auch etwas mit Höflichkeit zu tun ;)

Der schöne Günther 21. Mär 2013 08:27

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Was für eine Philosophie :-D
Hätte man Konfizius zu Multithreading-Programmierung gefragt, er hätte wahrscheinlich genau so geantwortet!

Wahrscheinlich wird es auch darauf hinauslaufen: Ich werde dem Thread auf die Fuße treten und entweder sagen, er soll mir mitteilen, was für Äpfel er gerade in seinen Händen hält oder mir ihm sagen, er soll mir mal einen bestimmten Apfel geben. Dabei kann er ja gleich noch eine Deep Copy des Apfels machen und ich kann mit dem Apfel fortan anstellen was ich will...

Blup 21. Mär 2013 08:37

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Vieleicht bietet das "visitor pattern" hier eine Lösung.
Wenn deine "TKlasse" als besuchtes Element im "accept" den Aufruf von "visit" mit "kritischerAbschnitt" kapselt, können beliebige Aktionen im Hauptthread ausgeführt werden.
Für jede Aufgabe kann man sich eine kleine Visitorklasse erstellen.

taveuni 21. Mär 2013 08:37

AW: Lesen einer außerhalb des Threads verwalteten Liste
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1208156)
[..] Dabei kann er ja gleich noch eine Deep Copy des Apfels machen [..]

Das würd ich aber nur tun wenn Du Apfelsaft damit machen willst. Den die Zeit und die Ressourcen welche für das klonen
und das freigeben verschwendet werden - müssen im Verhältnis zur Zeit der Blockade in der Critical Section berücksichtigt werden.


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