![]() |
Nachrichtenschleife bauen?
Hallo,
ich hab mich schon ein bisschen durch das Forum gewühlt auf der Suche wie man eine Nachrichtenschleife baut und diese selbst abarbeitet ohne zu großen Aufwand zu treiben. Zum Ausgangsproblem. Ich habe mehrere Komponenten (Edits, Comboboxen etc.) diese habe ich in einem Interface gebündelt und man kann auf dessen aktuellen Wert zugreifen. Das ganze soll aber aus dem Hauptthread passieren und aus N verschiedenen anderen Threads. Ich hatte das bis jetzt per SendMessage() gemacht, was soweit geklappt hat, aber irgendwann kam es dann zu Problemen wenn mehrere Threads darauf zugreifen. Hier mal der Codeausschnitt:
Delphi-Quellcode:
Man soll (so ist es jedenfalls gedacht) per Get/SetValue auf den Wert der Komponente zugreifen können. Dazu wird für jede Komponente bei der Erstellung ein virtuelles Fenster erzeugt. Wenn sich der Wert verändert, wird über das OnChange Event der aktuelle Wert in ein string (hier: FValue) geschrieben (durch MREW gesichert). Beim lesen über GetValue wird also nicht direkt von der VCL Komponente gelesen sondern von der FValue, was an sich ja ThreadSafe ist. Wenn jetzt jemand diesen Wert außerhalb des Eingabefeldes ändern möchte sollte dies über SetValue("Blub"); geschehen, aber das läuft noch gar nicht rund.
procedure TIBasic.WndProc(var Msg: TMessage);
begin if Msg.Msg = WM_CONTROL_VALUE_CHANGE then begin SetControlValue(WideString(Msg.WParam)); end else Msg.Result := DefWindowProc(FHandle, Msg.Msg, Msg.WParam, Msg.LParam); end; constructor TIBasic.Create; begin FHandle := AllocateHWnd(WndProc); // [...] end; function TIBasic.GetValue; begin FValueLock.BeginRead; try Result := FValue; finally FValueLock.EndRead; end; end; procedure TIBasic.SetValue(AValue: WideString); begin // SendMessage würde hier funktionieren PostMessage(FHandle, WM_CONTROL_VALUE_CHANGE, Integer(AValue), 0); end; procedure TIBasic.ControlOnChange(Sender: TObject); begin FValueLock.BeginWrite; try FValue := GetControlValue; finally FValueLock.EndWrite; end; // [...] end; function TIBasic.GetControlValue; begin Result := FEdit.Text; end; procedure TIBasic.SetControlValue(AValue: WideString); begin FEdit.Text := AValue; end; Da bekomme ich dann Teilweise ganz andere (von anderen Nachrichten) Werte in diese Felder, also irgendwie muss da noch was drum herum gebaut werden damit das läuft, aber da hakt es :/ Grüße |
AW: Nachrichtenschleife bauen?
Ich bin nicht sicher, ob ich Dein Vorhaben richtig verstanden habe, aber das scheint eine Art DataBinding werden zu sollen, richtig? In dem Fall solltest Du Dir vielleicht Stevies
![]() |
AW: Nachrichtenschleife bauen?
bei
Delphi-Quellcode:
ist der Zeiger auf AValue als Stackwert ungültig bis die Message abgearbeitet wird,da SetValue bereits wieder verlassen wurde.
PostMessage(FHandle, WM_CONTROL_VALUE_CHANGE, Integer(AValue), 0);
|
AW: Nachrichtenschleife bauen?
Zitat:
Dann noch das Gecaste mit dem bösen Integer. Nimm stattdessen den Typ LPARAM, bzw. WPARAM, LRESULT oder eben NativeInt und Co. Statt SendMessage kannst du auch Perform nutzen.
Delphi-Quellcode:
SendMessage(FHandle, WM_CONTROL_VALUE_CHANGE, LPARAM(AValue), 0);
Perform(WM_CONTROL_VALUE_CHANGE, LPARAM(AValue), 0); |
AW: Nachrichtenschleife bauen?
@DeddyH
Ja das hatte ich letztens schonmal gesehen. Hört sich sehr interessant an. @Bummi :thumb: Das muss man natürlich erstmal verinnerlichen. Wenn ich danach nun ein Application.ProcessMessages; funktioniert es. Aber ich glaube wenn das ein Thread aufruft ist das nicht so gut. Ich weiß gerade auch nicht so genau. @himitsu Okay habe den Integer verbannt und WPARAM Einzug halten lassen (aber das wäre ja sowieso nur für x64 interessant) Auf Perform kann ich ja gar nicht zugreifen (ist ja kein TControl).
Delphi-Quellcode:
TIBasic = class(TInterfacedObject, IBasic)
protected FEdit: TcxTextEdit; |
AW: Nachrichtenschleife bauen?
Warum nicht so?
Delphi-Quellcode:
procedure TIBasic.SetValue(AValue: WideString); begin FValue:=AValue; PostMessage(FHandle, WM_CONTROL_VALUE_CHANGE, 0, 0); end; if Msg.Msg = WM_CONTROL_VALUE_CHANGE then begin SetControlValue(FValue); |
AW: Nachrichtenschleife bauen?
Zitat:
Das macht viel Sßaß, wenn zwischenzeitlich keine Messages verarbeitet wurden (es gehen informationen verloren). Und wenn man das jetzt auch noch per multithread macht, dann geht voll die Post ab. :roll: Zitat:
PostMessage schreibt das in die MessageQueue und ProcessMessages arbeitet diese Queue ab. Natürlich wird das dann rechtzeitig abgarbeitet, bevor der Zeiger ungültig wird ... es werden allerdings alle Messages in der Queue verarbeitet. (und im Thread geht das eh nicht) Was macht denn nun SendMessage? Es schickt auch diese Nachricht los, aber dieses wird quasi sofort verarbeitet, bevor dieser Aufruf zurückkehrt. Und es wird NUR diese Nachricht verarbeitet und sonst nix (außer der MessageHandler ruft in sich ein ProcessMessages auf) |
AW: Nachrichtenschleife bauen?
SendMessage() ist aber auch blockierend.
SetValue() müsste dann nur den Wert in einer Liste (Schlange) speichern bis er in WndProc() abgearbeitet wurde. Dort wird der dann entfernt. So gehen keine Daten verloren. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz