AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Hm, stimmt...das die Werte noch an der Stelle im Speicher liegen, kann keiner garantieren.
Wie macht man es richtig? Einen Zwischenspeicher nehmen, also einen weiteren Stack/Liste als Membervariable in der eigenen TThread-Ableitung, und dort dann reinkopieren? |
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
s.o.
|
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Zitat:
So ist das jetzt eine runde Sache.
Delphi-Quellcode:
procedure TMessageThread.SendDateTime(const ADateTime : TDateTime);
var LDateTime : TDateTime; begin LDateTime := ADateTime; TThread.Queue(nil, procedure begin DoSendMessage(LDateTime); end); end; procedure TMessageThread.DoInternalExecute; begin while not Terminated do begin try FLock.Enter; try if FStack.Count >= 25 then begin if not Terminated then begin while FStack.Count <> 0 do begin SendDateTime(FStack.Pop); end; end; end; finally FLock.Leave; end; finally Sleep(100); end; end; end; procedure TMessageThread.DoSendMessage(const ADateTime : TDateTime); var LMessage : TDateTimeMessage; begin LMessage := TDateTimeMessage.Create(ADateTime); TMessageManager.DefaultManager.SendMessage(Self, LMessage, True); end; |
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Abgesehen davon, dass ich keinen Thread nehmen würde...
Weil die Message ruft Dich ja auf... Es gibt also keinen Grund zu "Pollen" |
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Ja, das Beispiel ist natürlich sinnbefreit, weil hier Daten aus dem Main-Thread in den anderen Thread und wieder zurückgeschaufelt werden.
Aber mir gings ja um die grundsätzliche Heransgehensweise. Über den TMessageManger können ja ganz andere Daten an einen Thread übergeben werden, der zum Beispiel nach N-Werten anfängt darauf eine lange Operation auszuführen und das Ergebnis wieder zurück an den Main-Thread zu übergeben. |
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Dann spendier dem Thread doch wenigstens einen Event damit der nicht immer wie doof herumrödelt auch wenn es nichts zu tun gibt.
|
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Zitat:
Delphi-Quellcode:
Tests ob der Thread noch läuft usw.. habe ich mir jetzt gespart...
procedure TMyThread.Execute;
begin while not(Terminated) do begin try E_Event.WaitFor(INFINITE); if Terminated then exit; MyExecute; // Hier findet die Eigentliche Verarbeitung statt. except end; end; end; ... FSaveID := TMessageManager.DefaultManager.SubscribeToMessage(TWhatever, Procedure(Const Sender:TObject;Const M:TFMXMessage) begin FVerarbeite := TWhatEver(M).Value.Daten; E_Event.SetEvent; end); ... |
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Soweit in Ordnung?
Ich löse das Event und damit die Verarbeitung aus, wenn der Thread mehr als 25 Items erhalten hat. Da ich die Instanz von TEvent im Formular erzeuge und dem TThread per Konstruktor übergebe, habe ich mir die Möglichkeit offen gelassen, ggf. auch aus dem Formular heraus das Event zu setzen. Kann man das so machen?
Delphi-Quellcode:
unit Messagner.View;
interface uses System.SysUtils, System.Classes, System.Types, System.Messaging, System.SyncObjs, System.Generics.Collections, Vcl.Controls, Vcl.Forms, Vcl.StdCtrls; type TIdleMessage = class(System.Messaging.TMessage) end; TDateTimeMessage = class(System.Messaging.TMessage<TDateTime>) end; TMessageThread = class(TThread) private FLock : TCriticalSection; FStack : TStack<TDateTime>; FEvent : TEvent; procedure GetIdleMessage(const Sender : TObject; const M : TMessage); procedure DoSendMessage(const ADateTime : TDateTime); procedure DoInternalExecute; procedure SendDateTime(const ADateTime : TDateTime); protected procedure Execute; override; procedure TerminatedSet; override; public procedure BeforeDestruction; override; constructor Create(const AEvent : TEvent); destructor Destroy; override; end; TForm1 = class(TForm) mmoLog : TMemo; procedure FormCreate(Sender : TObject); procedure FormDestroy(Sender : TObject); private FMessageThread : TMessageThread; FIdleMessage : TIdleMessage; FEvent: TEvent; procedure ThreadTerminated(Sender : TObject); procedure OnNewDateTimeMessage(const Sender : TObject; const M : TMessage); procedure LogToMemo(const Text : string); public procedure DoIdle(Sender : TObject; var Done : Boolean); end; var Form1 : TForm1; implementation {$R *.dfm} procedure TForm1.LogToMemo(const Text : string); begin mmoLog.Lines.Add(Text); end; procedure TForm1.OnNewDateTimeMessage(const Sender : TObject; const M : TMessage); var LMessage : TDateTimeMessage; begin LMessage := M as TDateTimeMessage; LogToMemo('- - - > ' + FormatDateTime('hh:mm:ss:zzz', LMessage.Value)); end; procedure TForm1.DoIdle(Sender : TObject; var Done : Boolean); begin TMessageManager.DefaultManager.SendMessage(Self, FIdleMessage, False); end; procedure TForm1.FormCreate(Sender : TObject); begin FIdleMessage := TIdleMessage.Create; Vcl.Forms.Application.OnIdle := DoIdle; FEvent := TEvent.Create(); FMessageThread := TMessageThread.Create(FEvent); FMessageThread.OnTerminate := ThreadTerminated; TMessageManager.DefaultManager.SubscribeToMessage(TIdleMessage, FMessageThread.GetIdleMessage); TMessageManager.DefaultManager.SubscribeToMessage(TDateTimeMessage, OnNewDateTimeMessage); end; procedure TForm1.ThreadTerminated(Sender : TObject); var LException : Exception; begin TMessageManager.DefaultManager.Unsubscribe(TIdleMessage, FMessageThread.GetIdleMessage); if Sender is TThread then begin if TThread(Sender).FatalException is Exception then begin LException := Exception(TThread(Sender).FatalException); LogToMemo(LException.ToString + ' ' + LException.Message); end; end; end; procedure TForm1.FormDestroy(Sender : TObject); begin FMessageThread.Free; FIdleMessage.Free; FEvent.Free; end; { TMessageThread } procedure TMessageThread.BeforeDestruction; begin FStack.Free; inherited; end; constructor TMessageThread.Create(const AEvent : TEvent); begin inherited Create; FEvent := AEvent; NameThreadForDebugging('Message-Thread'); FLock := TCriticalSection.Create; FStack := TStack<TDateTime>.Create; end; procedure TMessageThread.SendDateTime(const ADateTime : TDateTime); var LDateTime : TDateTime; begin LDateTime := ADateTime; TThread.Queue(nil, procedure begin DoSendMessage(LDateTime); end); end; procedure TMessageThread.TerminatedSet; begin inherited; FEvent.SetEvent; end; destructor TMessageThread.Destroy; begin inherited; FLock.Free; end; procedure TMessageThread.DoInternalExecute; begin FLock.Enter; try if FStack.Count >= 25 then begin if not Terminated then begin while FStack.Count <> 0 do begin SendDateTime(FStack.Pop); end; end; end; finally FLock.Leave; end; end; procedure TMessageThread.DoSendMessage(const ADateTime : TDateTime); var LMessage : TDateTimeMessage; begin LMessage := TDateTimeMessage.Create(ADateTime); TMessageManager.DefaultManager.SendMessage(Self, LMessage, True); end; procedure TMessageThread.Execute; var WaitResult : TWaitResult; begin inherited; while not Terminated do begin WaitResult := FEvent.WaitFor(); if WaitResult = TWaitResult.wrSignaled then begin if not Terminated then begin DoInternalExecute; end; end; end; end; procedure TMessageThread.GetIdleMessage(const Sender : TObject; const M : TMessage); var NowDateTime, LastDateTime : TDateTime; begin FLock.Enter; try NowDateTime := System.SysUtils.Now; if FStack.Count <> 0 then begin LastDateTime := FStack.Peek; if LastDateTime <> NowDateTime then begin FStack.Push(NowDateTime); if FStack.Count >= 25 then begin FEvent.SetEvent; end; end; end else begin FStack.Push(NowDateTime); end; finally FLock.Leave; end; end; end. |
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Zitat:
|
AW: Verständnisfrage zur Verwendung von TMessageManager im Thread
Zitat:
Delphi-Quellcode:
zu speichern ist doch nur optional?!
SubscribeToMessage
Unsubscribe hat doch noch zwei weitere Überladungen (http://docwiki.embarcadero.com/Libra...er.Unsubscribe). Bei einer relativ geringen Menge an
Delphi-Quellcode:
pro
Subscribers
Delphi-Quellcode:
ist die Iteration über die Liste doch stark vernachlässigbar oder täusche ich mich?
MessageClass
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:56 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