Einzelnen Beitrag anzeigen

berens

Registriert seit: 3. Sep 2004
434 Beiträge
 
Delphi 10.4 Sydney
 
#15

AW: Exception ohne wirklichen Auslöser treibt mich in den Wahnsinn!

  Alt 20. Aug 2013, 17:45
Oben schonmal im Nebensatz: OwnsObject wurde zu Testzwecken überall mal auf "False" gesetzt, weil ich einfach schätzungsweise alles ausprobiert habe, den Fehler zu finden.

Alle doppelten Listen und Variablen verfolgen den Zweck, dass ich auf gar keinen Fall mit dem Mainthread auf Variablen/Objekte von diesem Thread zugreife.

Ich habe das Grundkonzept von Threads und "eiserne Regel", dass man vom Main-Thread nicht Objekte von (m)einem Thread zugreift (und andersrum) schon verstanden, aber ich glaube, ich setze das total falsch um.

Aus lauter Angst, versehentlich auf Variablen und Objekte zuzugreifen die gerade de andere Thread verwendet, habe ich immer alle Variablen und Objekte doppelt. Eine nur für den Main-Thread (z.B. clProjekte, public) und eine nur für den Thread (FclProjekte, private). Einzig in Synchronize(SyncBlabla) werden die Objekte von Thread nach Main kopiert und andersherum. Auch hier erstelle ich wieder ausschließlich neue Objekte, die mit Assign die Werte zugewiesen bekommen, vor lauter Sorge, wenn ich ein Objekt, das im Thread erstellt wurde aus einer TComponentList extrahierte (.Extract) und der ComponentList vom Main-Thread hinzufüge, dass dieses Objekt sich nicht 100% garantiert genau so verhält wie eines, das im Main-Thread erstellt wurde (vll. wegen Owner oder sonst irgendwelchen "Objektinternen"-Werten).

Ich werde mir CriticalSection mal genauer anschauen. Dies habe ich bisher noch nie verwendet, da ich davon ausgegangen bin, dass bei dem TThread-Objekt Synchronize() das empfohlende Pendant zu CriticalSection (Threads mit purer Api) ist.

Ich habe auch schon mehrere Thread-Tutorials durchgelesen. Haut mich, wenn ich einfach dabei gepennt habe, aber vielleicht sammeln wird hier gerade nochmal die wichtigsten Fakten, "DOs und DON'Ts".

Ich programmiere mit diesen Grundsätzen im Hinterkopf, bitte ergänzt oder korrigiert mich hier:
(Der Einfachheit halber nenne ich nachfolgend alle Objekte und Variablen etc. nur noch "Variablen".)

1) Mit dem Main-Thread darf man niemals auf Thread-Variablen zugreifen -weder lesend noch schreibend- die jemals im Thread.Execute verwendet werden

2) Im Thread.Execute darf niemals auf externe Variablen zugegriffen werden -weder lesend noch schreibend- (außerhalb des eigenen Objekts)

3) Im Thread.Execute dürfen keine VCL-Komponenten (speziell auch sichtbare Objekte) verwendet werden

4) Im Thread.Execute darf niemals auf Variablen des Thread-Objekts zugegriffen werden, die irgendwann mal von extern gesetzt oder gelesen werden sollen/können (z.B. public Variablen).

5) Im Thread verwendete Komponenten und Units müssen "Thread-Sicher" sein

6) Regel 1, 2, 4 dürfen evtl. mit CriticalSection umgangen werden???

7) Objekte, die im Thread.Execute erstellt wurden (mit oder ohne Owner) und mit Synchronize an das Hauptprogramm übergeben werden, lassen das Universum kollabieren. Dito in die andere Richtung: Im Hauptprogramm erstellte Objekte -speziell welche mit z.B. Owner=frmMain- dürfen auch mit Synchronize nicht an den Thread.Execute übergeben werden (also der direkte Pointer auf das Objekt), selbst wenn Synchronize die Referenz im MainThread auf dieses Objekt löscht), da der Thread -weshalb auch immer- z.B. auf den Owner zugreifen könnte und alles abstürzt.

8) ".Terminate" setzt einfach nur die Variable "Terminated" auf True. Ob der Thread wirklich beendet wurde, erfahre ich nur, wenn ich dafür eine eigene Variable setzte. (z.B. meine blTerminated)

9) Es ist für TThread.Execute kein Unterschied, ob ich eine TComponentList in .Create oder .Execute erstelle.


So, jetzt bekomme ich von Euch bestimmt gleich dieses o.g. Thread-Halb-Wissen um die Ohrengehauen. Lasset den Sturm beginnen.

Ne im Ernst, manchmal mach Delphi wirklich viel im Hintergrund und ich weiss nicht so recht, ob ich "das jetzt machen darf oder nicht". Mit dieser Arbeitsintensiven doppelt und dreifach Abspeicherei der Objekte will ich wirklich 100% sicher gehen, dass mein Programm nicht wegen dem Zugriff von Thread und Mainthread auf die selbe Variable abstürzt.
  Mit Zitat antworten Zitat