![]() |
Tmemo und threads
Hallo zusammen,
ich habe eine Anwendung, die im Prinzip so aufgebaut ist:
Code:
(Ist stark vereinfacht)
PseudoCode
sqltext:=GetSQLText; if chk(sqltext) then Querythread; :EndofQuery case outtype of file: ReadQuerytoFile(filename); grid: ReadQuerytoGrid(self.Grid1); text: ReadQuerytoMemo(self.Memo1.Lines); :EndofReader curser:=cursordefault; ReadQuerytoGrid ruft selber eine procedure auf, die die Daten aus der Query in ein TStrings kopiert. Das sah im Prinzip so aus:
Code:
mystrings.beginupdate;
while not query.eof do begin mystrings(add(query.fieldbyname(Feld).asstring); query.next; end; mystrings.endupdate; Im Prinzip funktioniert das auch, wenn ich keine Textausgabe nutze. Dann wird die Ausgabe zu einem Glücksspiel. Mal werden die Daten übernommen aber nicht angezeigt- sieht aus wie
Delphi-Quellcode:
oder aber manchmal bekomme ich ein "ungültiges Fensterhandle" zurück.
TMemo.visible=false;
Ebenso kann es sein, daß die Übernahme angezeigt wird und die Ergebnisse auch sichtbar sind. Zum Testen habe ich den BeginUpdate/EndUpdate-Rahmen immer weiter vergrößert, aber das Verhalten bleibt gleich unberechenbar. z.Zt bin ich bei:
Code:
Meine nächste Maßnahme wäre, Die Ergebnisse in eine "externe" Stringlist/Strings/String zu schreiben und diese dann in das Memo zu kopieren. Auf diese Weise sollten sich die beiden Threads nicht in die Quere kommen. Was mich daran stört, ist der hohe Speicherverbrauch, und daß der Zugriff auf das Stringgrid aus dem ReaderThread heraus problemlos funktioniert.sqltext:=GetSQLText; if chk(sqltext) then begin Memo1.lines.Beginupdate; Querythread; :EndofQuery case outtype of file: ReadQuerytoFile(filename); grid: ReadQuerytoGrid(self.Grid1); text: ReadQuerytoMemo(self.Memo1.Lines); :EndofReader Memo1.Lines.Endupdate; curser:=cursordefault; Oder suche ich u.U. am falschen Ort nach der Fehlerursache? Ich hoffe das ist nicht zu wirr und vielen dank für's lesen. Gruß K-H |
AW: Tmemo und threads
Du fasst die Controls aber nur im Kontext des MainThreads an, richtig?
Denn wenn nicht, gibt es alles Mögliche (von tut bis kompletter Grütze :stupid:) |
AW: Tmemo und threads
"Anfassen" ist wohl das Stichwort. Da ich nicht weiß was der Mainthread so treibt, wenn ich es ihm nicht explizit sage, geht wohl kein Weg an dem "Zwischenpuffer" vorbei.
(Grütze ist schön und beschreibt das Verhalten recht genau!) Edith: ich hab's jetzt geändert:
Delphi-Quellcode:
Und es läuft so wie ich es gerne hätte! vielen Dank!
templl:=tstringlist.Create;
self.DataReaderThread:=TDBWriteData2TextThread.Create(ADODM.ADOQuery1,templl,self.Handle,true); procedure TForm1.CMEndRead(var msg:TMessage); begin Statusbar1.Panels[0].Text:=format('_## %d %d ',[msg.WParam,msg.LParam]); self.M_Text.Lines.BeginUpdate; // Übernehme Daten if assigned(templl) then begin self.M_Text.Lines.Capacity:=templl.Count; self.M_Text.Lines.Text:=Templl.Text; FreeandNil(templl); { da xx nach xx.Free nicht NIL sein muß} //templl.Free; end; self.M_Text.Lines.EndUpdate; screen.cursor:=crdefault; end; Gruß K-H |
AW: Tmemo und threads
M_Text.Lines.Capacity zuzuweisen bringt nichts, da das MEMO und seine API sowas nicht kennt.
Abgesehn davon, daß das Memo über die API den Text immer nur am Stück verwaltet/speichert und nicht zeilenweise. Dieses Memo.Lines (TMemoStrings) ist nur ein Wrapper/Umleitung zur WinAPI des Memo. Memo.Lines.Text = Memo.Text und das geht beides auf SetWindowText/WM_SETTEXT. Messages werden immer im Erstellungsthread der Empfangskomponente verarbeitet, also kann man aus jedem Thread senden und es wird automatisch syncronisiert.
Delphi-Quellcode:
SetWindowText(M_Text.Handle, PChar(templl.Text));
// oder SendMessage(M_Text.Handle, WM_SETTEXT, PChar(templl.Text), 0); // nur M_Text.Handle sollte man besser im MainThread auslesen, wenn man nicht sicherstellen kann, dass M_Text.HandleAllocated=True Wenn z.B. der Speicher nicht reicht, um den Text zu laden (=Exception), wird templl nicht freigegeben und auch das Memo zeigt nie wieder etwas an, da es weiterhin durch BeginUpdate gesperrt bleibt. |
AW: Tmemo und threads
Du musst nur aufpassen, dass deine Message-Queue nicht vollläuft, sonst werden diese Nachrichten von Windows einfach verworfen.
Hängt allerdings auch ab in welcher Frequenz du die Nachrichten herausknallst. |
AW: Tmemo und threads
Bei SendMessage/SetWindowText wird der Queue wohl nicht voll laufen, da das ja wartet, bis die Message verarbeitet wurde.
(da bräuchte man dann schon ganz viele Threads, die das gleichzeitig versuchen) Bei PostMessage sieht das anders aus, aber müsste das nicht einen Fehler geben, wenn der Queue voll ist und man das versucht noch rein zu quetschen? Und leider bietet Windows ja keinen (offiziellen) Weg, um rauszufinden, wie voll der Queue ist. :freak: |
AW: Tmemo und threads
Zitat:
![]() If the function fails, the return value is zero. To get extended error information, call GetLastError. Also... wie immer. Meistens. |
AW: Tmemo und threads
Zitat:
Zitat:
Zitat:
Gruß K-H |
AW: Tmemo und threads
Windows-Messages werden in dem Thread ausgeführt, in welchem ein Win-Control (GDI) erstellt wurde.
Die Delphi-Controls (TForm und alles darauf) werden im Hauptthread erstellt und somit werden deren Messages auch im Hauptthread verarbeitet. Du kannst also per SetWindowText an Edit.Handle von überall (anderer Thread oder gar andere Anwendung) etwas schicken und Windows synchronisiert das dann automatisch. |
AW: Tmemo und threads
IMHO wird da nichts synchronisiert, sondern der Anwendungsprozess fragt die Nachrichten-Warteschlange ab und verarbeitet die Nachrichten sofern denn welche vorliegen.
Eine Synchronisierung ist also gar nicht erforderlich :stupid: Diese Polling-Schleife befindet sich in
Delphi-Quellcode:
TApplication.Run
Delphi-Quellcode:
procedure TApplication.Run;
begin ... repeat try HandleMessage; except HandleException(Self); end; until Terminated; ... end; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:29 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 by Thomas Breitkreuz