AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Nachrichtenschleife bauen?

Ein Thema von geskill · begonnen am 8. Okt 2012 · letzter Beitrag vom 8. Okt 2012
Antwort Antwort
Benutzerbild von geskill
geskill

Registriert seit: 17. Feb 2007
Ort: NRW
420 Beiträge
 
Delphi 2010 Professional
 
#1

Nachrichtenschleife bauen?

  Alt 8. Okt 2012, 17:24
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:
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;
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.
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
Sebastian
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.542 Beiträge
 
Delphi 11 Alexandria
 
#2

AW: Nachrichtenschleife bauen?

  Alt 8. Okt 2012, 17:49
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 DSharp einmal ansehen, dann musst Du das Rad nicht selbst neu erfinden.
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#3

AW: Nachrichtenschleife bauen?

  Alt 8. Okt 2012, 17:51
bei
PostMessage(FHandle, WM_CONTROL_VALUE_CHANGE, Integer(AValue), 0); ist der Zeiger auf AValue als Stackwert ungültig bis die Message abgearbeitet wird,da SetValue bereits wieder verlassen wurde.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.166 Beiträge
 
Delphi 12 Athens
 
#4

AW: Nachrichtenschleife bauen?

  Alt 8. Okt 2012, 18:02
bei PostMessage(FHandle, WM_CONTROL_VALUE_CHANGE, Integer(AValue), 0); ist der Zeiger auf AValue als Stackwert ungültig bis die Message abgearbeitet wird, da SetValue bereits wieder verlassen wurde.
Das wollte ich auch grade sagen

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);
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von geskill
geskill

Registriert seit: 17. Feb 2007
Ort: NRW
420 Beiträge
 
Delphi 2010 Professional
 
#5

AW: Nachrichtenschleife bauen?

  Alt 8. Okt 2012, 18:16
@DeddyH
Ja das hatte ich letztens schonmal gesehen. Hört sich sehr interessant an.

@Bummi
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;
Sebastian
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#6

AW: Nachrichtenschleife bauen?

  Alt 8. Okt 2012, 18:21
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);
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.166 Beiträge
 
Delphi 12 Athens
 
#7

AW: Nachrichtenschleife bauen?

  Alt 8. Okt 2012, 18:33
Warum nicht so?
Rufe jetzt mehrmals hintereinander diese Methode auf.
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.

Zitat:
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.
Was mag da wohl passieren?
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)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von geskill
geskill

Registriert seit: 17. Feb 2007
Ort: NRW
420 Beiträge
 
Delphi 2010 Professional
 
#8

AW: Nachrichtenschleife bauen?

  Alt 8. Okt 2012, 18:57
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.
Sebastian
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz