![]() |
PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Vor einiger Zeit war es noch OK, dass ich mit PostMessage Daten aus einem Thread an WndProc geschickt habe. Funktioniert wunderbare und ich bin Synchronize() losgeworden.
Ich stelle mir jetzt aber ein paar Kernfragen: Synchronize aus einem Thread heraus Sychronisiert mit dem Hauptthread. Grob gesagt kann ich dann den zweiten Thread auch komplett weglassen wenn doch eh synchronisiert wird. Wie sieht das aus, wenn man PostMessage verwendet und die Daten in WndProc (andere Unit) auswertet und dort die GUI aktualisiert. Wird dann auch mit dem Hauptthread synchronisiert bzw. IST DAS überhaupt besser? Synchronize ist weg, das war mein Ziel. Ich möchte nun gerne auch Zeichen ketten schicken können. Dafür würde ich bei PostMessage bleiben, aber WndProc durch WMCopyData(var msg: TWMCopyData); austauschen, sodass ich Records schicken kann und flexibler bin. Hat das gravierende Nachteile? Wenn ja, wie sonst Daten aus einem Thread heraus schicken, sodass man die GUI aktualisieren kann ohne Synchronize verwenden zu müssen? |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
gruss |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Ich weiß nicht ob deine Frage ernst gemeint ist.
Wenn nicht und es Ironie ist, ignoriere ich sie einfach mehr oder weniger gekonnt. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
Ja sie ist ernst gemeint. WM_COPYDATA: WM_COPYDATA ist ein Message die in der Winproc ausgewertet wird aber du möchtest die WinProc entfernen bzw. damit austauschen? Wie geht das. gruss |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Wie wärs denn so? Ich kapiere noch immer nicht wieso du diese Frage gerade stellst.
Delphi-Quellcode:
So kann ich senden was ich will. Nur frage ich mich: besser das unflexible WndProc-Event nutzen oder das deutlich flexiblere WMCopyData (ersteres mit PostMessage, letzteres mit SendMessage).
type
TPostMessageData = record sString: string; sInt: Integer; end; PPostMessageData = ^TPostMessageData; Button1Click(Sender: TObject); var CopyData: TPostMessageData; begin CopyData.sString := 'String test'; CopyData.sInt := 99; SendMessage(Handle, WM_COPYDATA, 0, Integer(@CopyData)); end; procedure TFormReceiver.WMCopyData(var msg: TWMCopyData); begin ShowMessage(PPostMessageData(msg.CopyDataStruct).sString); end; Aus einem Thread heraus. Wenn ich das richtig verstanden habe, blockiert SendMessage den Thread erst einmal. Auch wenn es nicht lange ist. PostMessage, da asynchron, macht das wohl nicht. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
Das ist schlicht weg falsch und nicht möglich. Du kannst deine eigene Message Queue aus dieser ableiten aber die Winproc austauschen vergiss es. Lese doch einfach mal was du geschrieben hast. Zitat:
Sendmessage wartet auf die Rückgabe PostMessage eben nicht! Bin raus! gruss |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
Ich muss auf keine Rückgabe warten. Ich möchte einfach nur die GUI aus einem Thread heraus aktualisieren ohne Synchronize verwenden zu müssen :P WndProc zusammen mit Record und PostMessage:
Delphi-Quellcode:
Was ist denn davon zu halten einen ganzen Record zu übergeben und immer mit New einen anzulegen?procedure TForm1.Button1Click(Sender: TObject); var CopyData: PPostMessageData; begin CopyData := New(PPostMessageData); CopyData.sString := 'String test'; CopyData.sInt := 99; PostMessage(Handle, 50, 0, Integer(CopyData)); end; procedure TForm1.WndProc(var msg: TMessage); begin case msg.msg of 50: begin ShowMessage('WndProc: ' + PPostMessageData(msg.LParam)^.sString); end; end; inherited; end; |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
Delphi-Quellcode:
irgendwelche Probleme bereitet, oder warum wolltest du das loswerden?
Synchronize
Zitat:
Zitat:
![]()
Delphi-Quellcode:
vergleichen (hierbei läuft der aufrufende Thread auch weiter; anders als beim
TThread.Queue
Delphi-Quellcode:
).
TThread.Synchronize
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
Nachdem ich sehr viel in WndProc ausgelagert habe und PostMessage verwende, ist der Unterschied deutlich spürbar. Zitat:
Mein Ziel ist es, alle Synchronize und Queue aus den Threads zu bekommen. Daher habe ich mir das da oben mal zusammengestrickt. Record > PostMessage > WndProc. Frage ist nur, ob das in Ordnung ist? |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
WndProc und ![]()
Delphi-Quellcode:
bzw.
TThread.Synchronize
Delphi-Quellcode:
bleiben. Probier es mal mit Letzterem und beachte zusätzlich, dass du wirklich nur die erforderlichen Codestellen synchronisierst. Auch hilfreich kann sein, die GUI Aktualisierung nicht nach jedem Rechenschritt auszuführen. Wenn du z.b. eh nur eine ProgressBar updatest, kannst du das ja ggfls. auch ohne Probleme nur alle 1000 Iterationen oder so durchführen, ohne dass man als Mensch davon etwas mitbekommt.
TThread.Queue
In Ordnung ist deine Methode vermutlich auch, bloß machst du es dir dadurch unnötig schwer und reduzierst zudem wahrscheinlich auch die Lesbarkeit deines Codes. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Zitat:
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Geschickt würde ich nicht sagen. Ich setze einfach 08 und 15 zusammen und erhalte 0815-Lösungen.
Was könnt ihr Profis denn abschließend dazu sagen: Queue oder WndProc mit PostMessage und Record. Es geht hier um Threads die einiges zu tun haben und die GUI recht häufig und schnell hintereinander aktualisieren, da es um Live-Daten geht wenn man das so nennen kann. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Währe TThreadedQueue eventuell ein Weg?
Mit einem extra Thread der die GUI aktualisiert und der pull das Queue leert. So können mehreren Threads die das Queue per push voll machen ohne zu blockieren. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Von TThreadedQueue höre ich zum ersten mal.
Wie würde denn dann aus diesem Extra-Thread heraus aktualisiert. Auch wieder mit Synchronize? |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Ja mit Synchronize.
Ich habe kein Beispiel und habe damit bis jetzt nur eine Log Funktion umgesetzt aber die Idee fand ich gut. Wenn ich das richtig verstanden hatte dann funktioniert die TThreadedQueue wie eine Art Spender (z.B. Rollen Spender). Oben wird nachgefüllt und unten nach und nach leer gemacht. Ist im Grunde wie ein Puffer der den Job Threads die Warte Zeit abnimmt. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread heraus?
Nur dann wäre ich ja wieder beim Synchronize, wovon ich eigentlich weg möchte.
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Ich habe jetzt nicht gesehen ob es schon angesprochen wurde:
WM_COPYDATA muss mit SendMessage verwendet werden und WM_COPYDATA hat bei uns (früher) nicht als Kommunikation im Prozess funktioniert (nur zwischen Prozessen). |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
Ich glaube ich bleibe aber bei WndProc. Ob ich ein ganzes Record schicke muss ich noch gucken. Eventuell schicke ich Strings sogar nur so
Delphi-Quellcode:
PostMessage(receiver, command, wParam, Integer(PChar(string)));
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Hmm..
das mit WM_COPYDATA kann im selben Process nur funktionieren, wenn zwischen verschiedenen Threads.. Denn die Message kann im selben Thread nicht abgearbeitet werden, da diese ja noch auf das Return vom SendMessage wartet ;) Ich habe dies benutzt, um Texte aus Threads heraus an den MainThread zu schicken ohne Verwendung von Synchronize... |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Also WM_COPYDATA ist eigentlich eh nur für IPC gedacht. Wenn man damit eh gezwungenermaßen
![]()
Delphi-Quellcode:
, sprich: Der aufrufende Thread wird solange blockiert, bis das Mainthread die Nachricht abgearbeitet hat.
TThread.Synchronize
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Außer ich nutze PostMessage. Das entspricht dann ja, wie du sagtest, etwa Queue.
Was ist denn dann die richtige Methode um die GUI aus einem Thread zu aktualisieren? |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
![]() Zitat:
Delphi-Quellcode:
:)
TThread.Queue
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Nee Synchronize und Queue hab ich doch erst kürzlich fast völlig ausgemerzt und einen guten Performancevorteil spürbar gemacht :P
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Er könnte es ja eventuell auch mal mit PostThreadMessage versuchen.
Aber ich glaube das ist genauso wenig möglich wie mit PostMessage. laut MSDN wird davon abgeraten etwas anderes als SendMessage zu verwenden. gruss |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
Wo ich das gelesen habe weiß ich nicht mehr. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
Deine Performanceprobleme haben höchstwahrscheinlich andere Ursachen. Beliebter Anfängerfehler ist zum Beispiel der Versuch den Fortschritt einer Dateioperation (aus dem Internet downloaden oder Datei kopieren) im Mainthread per Progressbar sichtbar zu machen. Dabei wird jedes Datenpaket und/oder schlimmer noch jedes einzelne neue Byte an den Mainthread signalisiert, anstatt die prozentuale Änderung im Thread zu berechnen und damit maximal ca. 100 mal den Mainthread signalisieren zu müssen. Günstiger wären auch größere Schrittweiten möglich (5 oder 10 %). |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
Mit PostMessage sind die Probleme weg. Wieso wiederholt ihr dann immer wieder denselben Quark :roll: Ist mit jedenfalls ab sofort egal. Bin raus hier. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
Delphi-Quellcode:
). Falls du das komplette Projekt hochladen kannst/willst, würde ich sogar mal drüberschauen. Gerne auch per PN.
Tthread.Queue
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Liste der Anhänge anzeigen (Anzahl: 2)
Habe das jetzt nochmal getestet mit einem Thread, der exakt 1 Sekunde lang einen Wert in einer Schleife inkrementiert.
Bild 1 zeigt den endgültigen Wert der Variable nach Beendigung des Thread. Bild 2 führt nebenher den gleichen Task auch nochmal im Main Thread aus. Wie man sieht es lediglich
Delphi-Quellcode:
von der Performance her minimal schlechter.
TThread.Synchronize
Delphi-Quellcode:
ist genauso schnell wie
TThread.Queue
![]() ![]() Synchronisiert wird jeweils wenn
Delphi-Quellcode:
, also jeweils nach 100.000 Iterationen.
Value mod 100000 = 0
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Muss ich Queue aus dem Thread heraus aufrufen oder kann ich im Thread eine Prozedur in einer anderen Unit aufrufen und von dort aus Queue?
Wenn letzteres möglich ist, könnte ich Queue und PostMessage direkt gegenüberstellen und mit nur einer einzigen geänderten Zeile testen. |
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Zitat:
Delphi-Quellcode:
. Der Aufruf von
TThread.Queue(TThread.Current, ...)
Delphi-Quellcode:
könnte deinen Test allerdings verfälschen.
TThread.Current
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Ich bastel erstmal das Grundgerüst zusammen und gucke was sich dann anbietet.
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Liste der Anhänge anzeigen (Anzahl: 1)
Habe mein Testprojekt mal aufgeräumt und angehangen. Ist sicherlich keine ganz perfekte Messung, aber egal was ich probiere:
Delphi-Quellcode:
ist gleich schnell wie
TThread.Queue
Delphi-Quellcode:
und
PostMessage
Delphi-Quellcode:
gleich schnell wie
TThread.Synchronize
Delphi-Quellcode:
.
SendMessage
|
AW: PostMessage mit WndProc oder WMCopyData/Record aus Thread für GUI-Aktualisierung?
Dann bleibe ich der Einfachheit halber bei PostMessage. Das ist alles schon implementiert und kann nur besser gemacht werden.
Alles zu Queue umzuändern würde wieder alles über den Haufen werfen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:55 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