Du musst bedenken, dass dynamische Arrays in Delphi referenzgezählt werden, sodass du nicht einfach zuweisen kannst.
In deinem Code sind deutlich zu viele Critical Sections. Bedenke: Wenn nur ein Thread eine "einfache" Variable (z.B. einen Integer) beschreibt und alle anderen nur lesen, brauchst du gar keine Locks.
Ich würde ein neues Design vorschlagen: Du hast zwei globale Arrays. Eines ist enthält die gesamte bisherige Wurfstatistik. Auf das andere greifen alle Threads zu. Dazu musst du nur das Inc durch ein InterlockedIncrement ersetzen.
Im Timer tust du Folgendes: Ein drittes, lokales Array füllst du mit Nullen. Dann tauschst du dieses Array mit dem, auf das die Threads zugreifen, aus. Somit fangen die Threads wieder bei Null an zu zählen. Dann nimmst du das alte Array und addierst dessen Werte auf die globale Statistik. Aus diesem Array kannst du nun alle Daten abgreifen, ohne die Methoden der einzelnen Threads bemühen zu müssen.
Eine Skizze:
Delphi-Quellcode:
//Formular
WurfStatistik: TThrows;
//global
AktiveWuerfe: TThrows;
//Im Thread
//...
InterlockedIncrement(AktiveWuerfe[thrown - FCubesCount]);
//Im Timer
LokalesArray1 := AktiveWuerfe;
//Delphi erledigt das Nullen
SetLength(LokalesArray2, ArrayLaenge);
AktiveWuerfe := LokalesArray2;
Add(WurfStatistik, LokalesArray1);
//In Wurfstatistik sind jetzt alle vergangenen Würfe
//...
Und plötzlich kommen wir ohne Locks aus...