AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren

Tmemo und threads

Ein Thema von p80286 · begonnen am 22. Jun 2016 · letzter Beitrag vom 29. Jun 2016
Antwort Antwort
Seite 1 von 2  1 2   
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.658 Beiträge
 
Delphi 7 Personal
 
#1

Tmemo und threads

  Alt 22. Jun 2016, 13:37
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 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
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  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
 
#2

AW: Tmemo und threads

  Alt 22. Jun 2016, 14:46
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 )
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
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.658 Beiträge
 
Delphi 7 Personal
 
#3

AW: Tmemo und threads

  Alt 22. Jun 2016, 15:39
"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
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector

Geändert von p80286 (22. Jun 2016 um 17:45 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
38.596 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Tmemo und threads

  Alt 22. Jun 2016, 18:35
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu (22. Jun 2016 um 18:38 Uhr)
  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
 
#5

AW: Tmemo und threads

  Alt 22. Jun 2016, 18:41
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.
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
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
38.596 Beiträge
 
Delphi 10.4 Sydney
 
#6

AW: Tmemo und threads

  Alt 24. Jun 2016, 14:33
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014
  Mit Zitat antworten Zitat
sahimba

Registriert seit: 14. Nov 2011
Ort: Berlin, Hauptstadt der DDR
136 Beiträge
 
Delphi 10 Seattle Professional
 
#7

AW: Tmemo und threads

  Alt 24. Jun 2016, 14:40
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.
  Mit Zitat antworten Zitat
Benutzerbild von p80286
p80286

Registriert seit: 28. Apr 2008
Ort: Stolberg (Rhl)
6.658 Beiträge
 
Delphi 7 Personal
 
#8

AW: Tmemo und threads

  Alt 24. Jun 2016, 15:26
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.

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!

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
Programme gehorchen nicht Deinen Absichten sondern Deinen Anweisungen
R.E.D retired error detector
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
38.596 Beiträge
 
Delphi 10.4 Sydney
 
#9

AW: Tmemo und threads

  Alt 27. Jun 2016, 13:24
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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014
  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
 
#10

AW: Tmemo und threads

  Alt 27. Jun 2016, 13:31
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

Diese Polling-Schleife befindet sich in TApplication.Run
Delphi-Quellcode:
procedure TApplication.Run;
begin
  ...
      repeat
        try
          HandleMessage;
        except
          HandleException(Self);
        end;
      until Terminated;
  ...
end;
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 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 +2. Es ist jetzt 07:04 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf