AGB  ·  Datenschutz  ·  Impressum  







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

Object mit SendMessage an MainThread senden

Ein Thema von Captnemo · begonnen am 26. Jun 2014 · letzter Beitrag vom 27. Jun 2014
Antwort Antwort
Seite 3 von 3     123   
Benutzerbild von Captnemo
Captnemo

Registriert seit: 27. Jan 2003
Ort: Bodenwerder
1.126 Beiträge
 
Delphi XE4 Architect
 
#21

AW: Object mit SendMessage an MainThread senden

  Alt 27. Jun 2014, 09:50
So hab ich es jetzt letztlich im Moment auch gelöst. Im MainTread eine Tobjectlist, vom Thread innerhalb ein TCriticalSection Daten hinzu, und per postmessage benachrichtigen.

Aber ich will mir auch nochmal die TThread.Queue anschauen, denn das find auch ganz interessant.
Dieter
9 von 10 Stimmen in meinem Kopf sagen ich bin nicht verrückt. Die 10. summt dazu die Melodie von Supermario Bros.
MfG Captnemo
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

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

AW: Object mit SendMessage an MainThread senden

  Alt 27. Jun 2014, 13:44
Nein, SendMessage/PostMessage ist in Threads kein Problem.

Beides trägt die Message in den MessageQueue des Threads ein, in welchem die Komponente erstellt wurde, an die die Message geht.
Verarbeitet wird die Message dann immer von der Messagebehandlung im zugehörigen Thread (meist der Hauptthread).


TThread.Queue ist wie Synchronize, außer daß die Prozedur nicht sofort verarbeitet wird. (von dem "Bug" abgesehn, wenn man was vom MainThread aus daran übergibt)
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 stoxx
stoxx

Registriert seit: 13. Aug 2003
1.111 Beiträge
 
#23

AW: Object mit SendMessage an MainThread senden

  Alt 27. Jun 2014, 14:32
Eine Liste mit durch Critical Sections gesichertem Zugriff ist imho fast die einzige vernünftige Art Daten unter verschiedenen Threads auszutauschen. Dem Formular dann nur noch per PostMessage() parameterlos mitteilen, dass es da neues drin gibt, und dieses arbeitet immer schon Index 0 ab und löscht aus der Liste bis sie leer ist. FiFo-Style.
kann man zustimmen


Davon ab pausiert der Thread bis alle Handler von den Empfängern fertig sind, und das ist ja nun auch nicht ganz der Sinn von Parallelisierung.
besser Postmessage, oder SendMessageTimeOut verwenden, da bei SendMessage bis zur Bestätigung der Verarbeitung gewartet wird, da hätte man dann auch gleich synchronize verwenden können, wo der Thread ebenso bis zum Ende der Verarbeitung angehalten wird.


Am Rande: SendMessage() ist in Threads, wenn ich mich nicht grad irre, eigentlich sogar ein ziemliches NoGo, da alles was die Empfänger dann tun auf ein Mal im Thread-Kontext statt findet. Und das kann je nach dem auch schon mal so richtig böse knallen, da es OS Ressourcen gibt, die nur im erstellenden Kontext verwendet werden dürfen.
nein, das stimmt nicht, das ist kein Problem.
PostMessage, SendMessage usw geht in de Queue vom jeweiligem Thread.
Überprüfen kannst Du, von welchem Thread die Funktion aufgerufen wird mit: GetCurrentThreadID

Wenn ein eigener Thread wirklich seine Nachrichten auch behandeln will, sofern er überhaupt welche bekommt, dann mit PeekMessage, TranslateMessage in der Execute Schleife von TThread.
Phantasie ist etwas, was sich manche Leute gar nicht vorstellen können.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#24

AW: Object mit SendMessage an MainThread senden

  Alt 27. Jun 2014, 15:23
Danke für die Aufklärung! War bisher zu faul das genauer zu testen. Das Problem was ich mal hatte wodurch ich dazu kam, war gelöst als ich noch eine ganze Menge mehr umgebaut habe. Das war dann also schon mal nicht der Suppenspucker.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#25

AW: Object mit SendMessage an MainThread senden

  Alt 27. Jun 2014, 16:42
Um noch einmal auf das Über- und Freigeben von Instanzen durch, von, über in Verbindung von Thread und Mainthread zu sprechen zu kommen ...

Was soll denn hier erreicht werden?

Nehmen wir einmal das Beispiel mit TLogMessage .

Wir haben da also einen Thread, der irgendwas bearbeitet und zwischendurch immer wieder etwas melden soll. Dieser Thread soll aber durch das Senden dieser LogMessage nicht mehr als nötig ausgebremst werden (seine Hauptaufgabe besteht eben nicht im Versenden dieser LogMessage). Ok.

Warum versendet dieser Thread diese LogMessage denn dann überhaupt?

Geben wir diesem Thread doch einen Kumpel an die Hand, der dieses Versenden für ihn übernimmt.
Und dieser Kumpel darf ja auch gerne wiederum ein Thread sein (macht ja nichts).
Delphi-Quellcode:
type
  TBaseMessage = class abstract
  end;

  TNotifyMessageEvent = reference to procedure( Sender : TObject; AMsg : TBaseMessage );

  TMessageService = class( TThread )
  private
    FCS : TCriticalSection;
    FEvent : TEvent;
    FMessages : TQueue<TBaseMessage>; <--- da kommen die rein
    FOnMessage : TNotifyMessageEvent;
    function GetOnMessage : TNotifyMessageEvent;
    procedure SetOnMessage( const Value : TNotifyMessageEvent );
    procedure DoSendMessage( AMessage : TBaseMessage );
  protected
    procedure Execute; override;
    procedure TerminatedSet; override;
  public
    constructor Create;
    destructor Destroy; override;

    procedure AddMessage( AMessage : TBaseMessage );

    property OnMessage : TNotifyMessageEvent read GetOnMessage write SetOnMessage;
  end;

constructor TMessageService.Create;
begin
  inherited Create( False );
  FCS := TCriticalSection.Create;
  FEvent := TEvent.Create( nil, False, False, '' );
  FMessages := TObjectQueue<TBaseMessage>.Create;
end;

destructor Destroy;
begin

  inherited;
  FMessages.Free;
  FEvent.Free;
  FCS.Free;
end;

function TMessageService.GetOnMessage : TNotifyMessageEvent;
begin
  FCS.Enter;
  try
    Result := FOnMessage;
  finally
    FCS.Leave;
  end;
end;

procedure TMessageService.SetOnMessage( const Value : TNotifyMessageEvent );
begin
  FCS.Enter;
  try
    FOnMessage := Value;
  finally
    FCS.Leave;
  end;
end;

procedure TMessageService.AddMessage( AMessage : TBaseMessage );
begin
  FCS.Enter;
  try
    FMessages.Enqueue( AMessage );
    FEvent.SetEvent; // <-- Den MessageService aufwecken
  finally
    FCS.Leave;
  end;
end;

procedure function TMessageService.GetOnMessage : TNotifyMessageEvent;
begin
  FCS.Enter;
  try
    Result := FOnMessage;
  finally
    FCS.Leave;
  end;
end;

procedure TMessageService.TerminatedSet;
begin
  inherited;
  FEvent.SetEvent;
end;

procedure TMessageService.DoSendMessage( AMessage : TBaseMessage );
var
  LOnMessage : TNotifyMessageEvent;
begin
  LOnMessage := OnMessage;
  if Assigned( LOnMessage ) then
    LOnMessage( Self, AMessage );
end;

procedure TMessageService.Execute;
var
  LMessage : TBaseMessage;
begin
  inherited;
  while not Terminated do
  begin
    FEvent.WaitFor; // Wir warten, bis sich was tut
    if not Terminated then
    begin
      // Nachricht aus der Queue holen
      FCS.Enter;
      try
        LMessage := FMessages.Extract;
        // Wenn noch Nachrichten in der Queue sind, dann den Event wieder setzen
        if FMessages.Count > 0 then
          FEvent.SetEvent;
      finally
        FCS.Leave;
      end;
      // Nachricht versenden
      Synchronize( procedure begin DoSendMessage( LMessage ); end );
      // Nachricht freigeben
      LMessage.Free;

    end;
  end;
Dieser MessageService übernimmt die Verwaltung für die Message-Instanz, liefert diese Message per Synchronize an wen auch immer aus. Das hat aber dann mit dem eigentlichen Thread, der da am arbeiten ist schon nichts mehr zu tun.

Schon ist der Drops gelutscht und jeder macht nur ein wenig und nicht alles oder kreuz und quer durcheinander gewürfelt.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 3     123   


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 01:23 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