Nachdem ich das Projekt nun per PN erhalten habe, habe ich beim Debuggen einmal die Maus drüber gehalten:
Ein Blick in den Quelltext hat mir auch gezeigt warum. Einmal zur Erklärung:
TDSServerClass verwaltet wie du denke ich weißt die Verbindungsklassen. Wenn nun ein Client anfragt, wird die Klasse mit OnGetClass ermittelt. Für jede neue Verbindung wird diese nun ggf. neu erzeugt.
Aber wenn "DataSnap" das tut, weiß das ja nichts von deinem Parameter. Stattdessen wird der Standardkonstruktor aufgerufen, den du aber nicht überschrieben hast.
Du hast also ein neues Verbindungsobjekt, das nun aber die GUI gar nicht bekommen hat.
Lösung:
Benutze auch OnCreateInstance der TDSServerClass und erzeuge das Verbindungsobjekt selbst:
Delphi-Quelltext
1: 2: 3: 4:
| procedure TGUI.DSMuehleClass_serverCreateInstance(DSCreateInstanceEventObject: TDSCreateInstanceEventObject); begin DSCreateInstanceEventObject.ServerClassInstance := TClientVerbindung.Create(Self); end; |
Dann zur Synchronisation:
Die fehlt in der Tat. Das sieht z.B. so aus, wenn es asynchron passieren soll (mit Synchronize würde der Aufruf warten bis der Aufruf ausgeführt ist):
Delphi-Quelltext
1: 2: 3: 4: 5:
| TThread.Queue(nil, procedure begin dieGUI.verbunden(); end); |
Dass es verschiedene Threads sind, siehst du in den beiden Bildern im Anhang. Der eine Screenshot ist beim Aufruf von TThread.Queue, der zweite bei der Ausführung darin. In der Threadliste siehst du, dass du jeweils in verschiedenen Threads bist wie ich ja schon geschrieben hatte. Aber ich wollte dir auch noch zeigen wie man das sehen kann.
(// EDIT: Wenn die Ausführung angehalten ist, ist man in dem Thread, bei dem Haltepunkt steht.)
Die GUI so fest mit der Steuerung zu verbandeln ist aber ohnehin nicht gut. Besser wären Events, die du mit Methoden in der GUI verbindest. Also im Prinzip sowas:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11:
| type TOnConnect = procedure(...) of object;
property OnConnect: TOnConnect read FOnConnect write FOnConnect;
if Assigned(FOnConnect) then TThread.Synchronize(nil, procedure begin FOnConnect(...); end; |
Das macht es auch einfacher alles in unterschiedliche Units zu packen. Denn das ist auch sehr sinnvoll.