Autor Beitrag
Gausi
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: Fr 16.08.19 14:55 
Ich bin da gestern auf ein komisches Problem gestoßen. Oder andersrum wundere ich mich ein wenig, dass da bisher kein Problem aufgetreten ist. :gruebel:

Ich war dabei, in einer recht unübersichtlichen Form etwas aufzuräumen, und z.B. ein paar Quick&Dirty-Timer zu ersetzen. Ich weiß, dass TimeSetEvent veraltet ist, aber das habe ich an ein paar anderen Stellen noch im Code, und solange es läuft ... ja nu.

Punkt ist, laut Dokumentation läuft das in einem separaten Thread, inklusive der Callback-Funktion. In sämtlichen Beispielen wird das aber munter als TTimer-Ersatz genutzt, auch immer schön mit Zugriff auf VCL-Komponenten. Das sollte ja aber eigentlich nicht gemacht werden - VCL und Threads nur synchronisiert.

Auf das Problem bin ich gestoßen, weil der VirtualStringTree bei BeginUpdate dann eine Exception wirft, Codestelle im VST-Code ist
ausblenden Delphi-Quelltext
1:
Assert(GetCurrentThreadId = MainThreadId, 'UI controls like ' + Classname + ' should only be manipulated through the main thread.');					


Frage: Sind nun alle Codefetzen dazu im Netz kaputt, oder haben wir hier eine Art light-Version von Threads, die problemlos mit der VCL interagieren kann?

_________________
We are, we were and will not be.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 18.08.19 00:25 
user profile iconGausi hat folgendes geschrieben Zum zitierten Posting springen:
Frage: Sind nun alle Codefetzen dazu im Netz kaputt, oder haben wir hier eine Art light-Version von Threads, die problemlos mit der VCL interagieren kann?
Solche Threads gibt es nicht, die Codebeispiele sind falsch. Wie so einiges, wenn es um Threads geht...
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: So 18.08.19 09:50 
Gut, danke. Das hatte ich befürchtet. Wundert mich nur etwas, da ich das an ein oder zwei Stellen nutze, wo wirklich "gearbeitet" wird, und es da eigentlich dann regelmäßig knallen sollte. Tut es aber nicht (ja ich weiß, das ist kein Argument :mrgreen:).

Dann ersetze ich den Code durch ein paar TTimer, die ich im FormCreate erstelle, um das Formular im Designer etwas übersichtlicher zu gestalten. (Wirklich nur ein paar, die auch die meiste Zeit über inaktiv sind, keine Angst. :lol: )

_________________
We are, we were and will not be.
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19272
Erhaltene Danke: 1740

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: So 18.08.19 12:10 
Letztlich kannst du auch einfach TThread.Queue oder ähnliche Funktionen zur Synchronisierung nutzen. Dann ist die Umstellung vermutlich einfacher.
Gausi Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 8535
Erhaltene Danke: 473

Windows 7, Windows 10
D7 PE, Delphi XE3 Prof, Delphi 10.3 CE
BeitragVerfasst: So 18.08.19 15:14 
Ne, das brauche ich da nicht, das mit dem TTimer passt schon. Die TimeSetEvents setze ich ohnehin im VCL-Thread. Da ändere ich dann die lose Callback-Prozedur einfach in ein TNotifyEvent ab, und füge im Create der Form ein paar Zeilen hinzu, um diese dem Timer als OnTimer-Event zuzuweisen. Generell sind meine TThreads schon recht sauber synchronisiert, denke ich.

Die TimerEvents nutze ich, um gelegentlich den Thread-Status abzufragen bzw. anzuzeigen. Bei der Abfrage bin ich jetzt noch über einen Kommentar im Fremdcode gestolpert, dass der Zugriff von der TRL (= RTL?) synchronisiert wird - aber das habe ich jetzt auch umgangen, indem ich mir diese Info von anderen Synch-Messages abgreife (und in eine VCL-Variable kopiere), die ohnehin kommen. Im VCL-Timer zur Aktualisierung einiger Label frage ich dann diese Kopie ab, nicht mehr das "Original" aus der Thread-Klasse.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
function TSearchTool.GetCurrentDir: UnicodeString; // getter für eine Property
begin
  Result:=FCurrentDir; //wird von der TRL synchronisiert
end;

Ich könnte natürlich auch die Threadklasse umschreiben, damit die alle x Millisekunden eine Nachricht an das Fenster sendet ... :nixweiss:

Anderer Einsatzzweck für diese Timer ist das erneute Laden eines Bildes nach einem Resize einer TImage-Komponente, da TImage.Stretch teilweise arg pixelige Ergebnisse liefert. Das direkt im OnResize ist unnötig (und flackert auch), daher starte ich dort nur einen Timer. Der erledigt das Laden dann nach ca. einer Sekunde, wenn der User fertig mit dem anpassen der Größe ist. Solche Dinge halt.

_________________
We are, we were and will not be.