AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

TDictionary und TThread

Ein Thema von MicMic · begonnen am 26. Feb 2020 · letzter Beitrag vom 27. Feb 2020
Antwort Antwort
MicMic

Registriert seit: 26. Mai 2018
296 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#1

TDictionary und TThread

  Alt 26. Feb 2020, 01:37
Delphi-Version: 10.3 Rio
Hallo,
Ich kenne das Problem, weiß aber nicht wie man es löst.
Also ich habe ein TThread der 2x (also für 2 x TMyComp) läuft.
Soweit klappt eigentlich alles. Natürlich aber nicht mit einem TDictionary.
Ich kürze mal ab.
Delphi-Quellcode:
TMyThread = Class(TThread)
  Protected
  Procedure Execute; Override;
End;

TMyComp = Class
  CThread : TMyThread;
End;

Var dic : TDictionary // von überall verwendbar

Procedure TMyThread.Execute;
Begin
  If dic.ContainsKey(lowercase(daten)) = False Then
  Begin
    ...code
    dic.Add(lowercase(daten),wert)
    // Code+dic.add eigentlich in einer weiteren Prozedur
  End Else
  Begin
    ...code
    dic.TryGetValue(lowercase(daten),wert);
    // Code+dic.add eigentlich in einer weiteren Prozedur
  End;
End;
TDictionary ist <string><string>. Jedenfalls wird aus den beiden Komponenten (TMyComp) was geladen und diese Daten will ich mit einem einzelnen TDictionary abspeichern. So könnte Komponente1 und Komponente2 stets die Daten aus dem TDictionary abfragen und sie müssten nicht die Daten laden. Das beißt sich natürlich, sprich wenn 1. Thread ein TDictionary halb abgespeichert hat und der 2. Thread meint, er ist schon komplett vorhanden. Das geht natürlich nicht. Natürlich bekam ich auch schon ein Fehler "Duplikate nicht erlaubt". Was natürlich klar ist, wenn hier ein neuer TDictionary Eintrag noch nicht von Komponente1 abgeschlossen/gespeichert ist und Komponente2 ihn ebenfalls erstellen will. Ich bin mal über "CriticalSection" gestolpert aber mir ist das ehrlich gesagt zu hoch für mein Hirn. War immer so viel Source-Code

Kann mir da evtl. jemand helfen? Vielleicht gibt's ja auch noch eine andere Lösung?

Geändert von MicMic (26. Feb 2020 um 01:53 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#2

AW: TDictionary und TThread

  Alt 26. Feb 2020, 02:01
TCriticalSection ist ja Windows MSDN-Library durchsuchenEnterCriticalSection, auch wenn Delphi diese Klasse schon für andere Plattformen erweitert hat.

Hier könnte man zwar auch einen MultiReaderSingleWriter verwenden, da sich das Dictionary parallel auslesen ließe, aber wenn nicht soooooo oft gelesen wird, dann lohnt es sich nicht.
Delphi-Referenz durchsuchenTSimpleRWSync bzw. Delphi-Referenz durchsuchenTMultiReadExclusiveWriteSynchronizer/TMREWSync

Dann gibt es noch das "neuere" TMonitor in der System-Unit, welches sich nativ an jedes TObject hängen lässt. (mit dem Namen der nicht mit TMonitor aus Forms zu verwechseln ist)

Es gibt auch eine TThreadList, was eine TList ist und bereits sowas wie eine CriticalSection enthält.
Add, Remove und Clear sind bereits threadsave und ansonsten kann man sich die innere TList auch gesperrt rausholen und längere Aktionen mit der Liste machen, während die anderen Threads warten.

Und im Grunde kommt kommt alles auf's Gleiche drauf raus, du mußt die Liste sperren (mindestens) wenn die Liste bearbeitet wird, bzw. auch für die "kurze" Rechenpause zwischen Nachsehn und das Machen.
Delphi-Quellcode:
TMonitor.Enter(List);
try
  if not List.Find(xyz) then
    List.Add(xyz);
finally
  TMonitor.Exit(List);
end;
Atomare Operationen braucht man nicht selbst absichern, wie z.B. InterlockedIncrement bzw. das plattformunabhängige AtomicIncrement oder das TThreadList.Add,
aber alles Andere muß geschützt werden, wie z.B. im Beispeispiel die Lücke zwischen If, Find und Add, wo ja ein anderer Thread zwischendurch das auch einfügen kann und das Ergebnis vom IF somit schon nicht mehr stimmt, wenn Add ausgeführt wird.

Alle anderen Sperr-Klassen mußt du ja neben dein zu Sperrendes legen, während TMonior direkt an der Klasse hängt, aber mit dem "Nachteil", dass man in der Definition nichts von dieser Sperr-Instanz sieht.
Hier kann man aber das Verhalten des Compilers ausnutzen, dass er unbekannte Attributklassen einfach ignoriert,
um hier in der Deklaration zu "dokumentieren", dass unten TMonitor verwendet wird.
Delphi-Quellcode:
var
  [Monitor] // oder [Lock]
  List: TDictionary<string,string>;
Delphi-Quellcode:
type
  MonitorAttribute = class(TAttribute);

var
  [Monitor]
  List: TDictionary<string,string>;
PS: Globale Variablen sind eh böse und ich würde das Dictionary als Class Var in die Threadklasse integrieren.
Delphi-Quellcode:
type
  TMyThread = class(TThread)
  public class var
    List: TDictonary<string,string>;
  protected
    procedure Execute; override;
  end;

// von außerhalb
TMyThread.List[abx] := def; //TMyThread.List.Add(abx, def);
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (26. Feb 2020 um 02:23 Uhr)
  Mit Zitat antworten Zitat
MicMic

Registriert seit: 26. Mai 2018
296 Beiträge
 
Delphi 10.2 Tokyo Starter
 
#3

AW: TDictionary und TThread

  Alt 27. Feb 2020, 01:25
Dankeschön für die Hilfe.
Noch habe ich keine Zeit gefunden... ist für mich jetzt auch nicht einfach. Aber ich erstelle mal ein neues Projekt und versuche mich da mal dran.
Aber ich habe mal für mein Projekt eine andere Idee umgesetzt. Wenn Thread 1 läuft, mach ich Pause für Thread 2 (und umgekehrt). So kann für's TDictionary nicht gleichzeitig gleiche Einträge erstellt werden. Und wenn die Abfragen von Werten nicht gerade klappt, werden halt die Daten geladen. Die Sache wird auch fast nur bei Programmstart schwierig. Dafür kann ich noch ein wenig tricksen. Im Programmverlauf werden dann eher selten gleiche Daten für's TDictionary erstellt und die Idee mit dem pausieren eines Threads und somit ab und zu doppeltes laden von Daten hält sich in Grenzen.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.033 Beiträge
 
Delphi 12 Athens
 
#4

AW: TDictionary und TThread

  Alt 27. Feb 2020, 01:55
Was, du hälst von außen den anderen Thread an fragwürdig undefinierter Stelle an?
Delphi-Referenz durchsuchenTThread.Suspend

Wenn das, dann NIEMALS, schäm dich, steinigt ihn, ...
Nicht umsonst wurden Resume/Suspend inzwischen als deprecated deklariert.

Mit etwas Glück kann man durch sowas sein komlettes Programm lahmlegen,
z.B. wenn der Thread gerade dabei war beim MemoryManager eine Speicheranforderung zu machen (Get/Free/Alloc/Realloc/...) und der Thread gerade da pausiert wird, wo er eine der CriticalSections im Manager blockiert hat und der andere Thread im selben Speicherbereich etwas machen will.

Für eine "einfache"/billige Threadabsicherung ohne eigene Sperrinstanz kann man auch SendMessage oder TThread.Synchronize/Queue benutzen.
Delphi-Quellcode:
procedure ...;
var
  B: Boelean;
begin
  ...
  //Synchronize(procedure // innerhalb einer TThreadklasse
  TThread.Synchronize(nil, procedure
  begin
    B = List.Find(xxx);
  end);
  if B then
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (27. Feb 2020 um 02:04 Uhr)
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
4.075 Beiträge
 
Delphi 12 Athens
 
#5

AW: TDictionary und TThread

  Alt 27. Feb 2020, 07:59
Statt Suspend würde ich da irgendwas mit Schleife, Wait und Event machen.
https://stackoverflow.com/questions/...ce-to-start-up
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:00 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