Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Tmemo und threads (https://www.delphipraxis.net/189536-tmemo-und-threads.html)

p80286 22. Jun 2016 12:37

Tmemo und threads
 
Hallo zusammen,
ich habe eine Anwendung, die im Prinzip so aufgebaut ist:
Code:
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;
(Ist stark vereinfacht)

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:
TMemo.visible=false;
oder aber manchmal bekomme ich ein "ungültiges Fensterhandle" zurück.
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:

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;
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.

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

Sir Rufo 22. Jun 2016 13:46

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:)

p80286 22. Jun 2016 14:39

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:
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;
Und es läuft so wie ich es gerne hätte! vielen Dank!


Gruß
K-H

himitsu 22. Jun 2016 17:35

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.

Sir Rufo 22. Jun 2016 17:41

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.

himitsu 24. Jun 2016 13:33

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:

sahimba 24. Jun 2016 13:40

AW: Tmemo und threads
 
Zitat:

Zitat von himitsu (Beitrag 1340990)
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?

Gibt es ja auch. https://msdn.microsoft.com/de-de/lib...(v=vs.85).aspx
If the function fails, the return value is zero. To get extended error information, call GetLastError.
Also... wie immer. Meistens.

p80286 24. Jun 2016 14:26

AW: Tmemo und threads
 
Zitat:

Zitat von himitsu (Beitrag 1340811)
M_Text.Lines.Capacity zuzuweisen bringt nichts, da das MEMO und seine API sowas nicht kennt.

Wenn ich mich richtig erinnere hilft es aber bei anderen Tstrings-abkömmlingen und hier schadet's nicht. So hatte ich die OH verstanden.

Zitat:

Zitat von himitsu (Beitrag 1340811)
Abgesehn davon, daß das Memo über die API den Text immer nur am Stück verwaltet/speichert und nicht zeilenweise.

Das werde ich mir rahmen!

Zitat:

Zitat von himitsu (Beitrag 1340811)
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.

Davon hab ich kaum ein Wort verstanden, wohl weil ich mich noch nicht so recht mit Mesages beschäftigt habe.

Gruß
K-H

himitsu 27. Jun 2016 12:24

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.

Sir Rufo 27. Jun 2016 12:31

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 05:33 Uhr.
Seite 1 von 2  1 2      

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