Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Mehrfachen Schleifenaufruf verhindern (https://www.delphipraxis.net/195174-mehrfachen-schleifenaufruf-verhindern.html)

sko1 8. Feb 2018 12:12

Mehrfachen Schleifenaufruf verhindern
 
Hallo,

ich dreh mich im Kreis und hoffe auf einen Denkanstoß:

Per WMCOPYDATA bekomme ich eine Message und diese ruft eine Procedure auf, in welcher eine Schleife abgearbeitet wird.
In dieser Schleife gibt es ein Application.Processmessages.

Wenn da aber nun wiederum eine solche Message einläuft, soll die bestehende Schleife abgebrochen und mit den Parametern der neuen Message wieder gestartet werden.

Irgendwie finde ich kein Konstrukt welches mir dies ermöglicht :-(

Ciao
Stefan

Stevie 8. Feb 2018 12:51

AW: Mehrfachen Schleifenaufruf verhindern
 
Delphi-Quellcode:
Application.ProcessMessages
rausnehmen, herausfinden, warum das dort eingebaut wurde (in den meisten Fällen, um die UI vermutlich responsive zu halten) und es anders lösen.

Uwe Raabe 8. Feb 2018 13:02

AW: Mehrfachen Schleifenaufruf verhindern
 
Zitat:

Zitat von Stevie (Beitrag 1393372)
Delphi-Quellcode:
Application.ProcessMessages
rausnehmen

:thumb::thumb::thumb:

sko1 8. Feb 2018 13:07

AW: Mehrfachen Schleifenaufruf verhindern
 
Da liegt das Problem:

Benutzer tippt in einer WPTools Tabelle...

Wenn er da z.B. im Preis tippt, wird eine Message ans Hauptprogramm generiert welches dann in einer Schleife wiederum Messages an die Tabelle sendet weil da dadurch z.B. Summenzellen geändert werden müssen.

Diese Textänderung beim Tippen wird (leider) nur durch Application.Processmessages sichtbar (oder wenn die Schleife abgearbeitet ist), es gibt in den WPTools nichts was die Anzeige neu erzwingt :-(

Die erste Message startet also die Schleife und will 100 Zeilen auf "12,35" ändern
Während die Schleife läuft kommt eine weitere Message rein und die Schleife will 100 mal auf "34,56" ändern.

Logge ich die Messages mit sehe ich z.b.

"12,35"
"12,35"
...
"12,35"
"34,56"
"34,56"
"34,56"
... 100mal
"34,56"
"34,56"
und dann die restlichen
"12,35"
"12,35"
"12,35"
"12,35"

Wie kann ich das umgehen?
Ich denke schon an eine generische Liste der die Messages aus der Schleife übergeben werden und die dann z.B. mit Timer oder Thread abgearbeitet wird, aber während die Schleife diese Liste füllt hängt die Anzeige in der Tabelle oder die Liste wird mit Processmessages genau so gefüllt wie auch in der direkten Abarbeitung in der Schleife...

Ciao
Stefan

jziersch 8. Feb 2018 13:43

AW: Mehrfachen Schleifenaufruf verhindern
 
Hallo

Zitat:

Diese Textänderung beim Tippen wird (leider) nur durch Application.Processmessages sichtbar (oder wenn die Schleife abgearbeitet ist), es gibt in den WPTools nichts was die Anzeige neu erzwingt
Doch natürlich. Normalerweise passiert bei WPTools der Bildschirmaufbau erst in Paint, also in der nächsten Idle Phase, man kann aber sowohl das Text formatieren als auch die Bildschirmausgabe erzwingen. Dafür einfach Paint direkt aufrufen.

Kleiner Test:
Code:
  for i := 1 to 100 do
  begin
    WPRichText1.ActiveParagraph.Append(IntToStr(i));
    WPRichText1.ReformatAll;
    WPRichText1.Paint;
    Sleep(50);
  end;
Um das besagte Problem zu lösen würde ich den Event ChangeSelection und nicht OnChange, da erstere asynchron aufgerufen wird, also nicht unmittelbar nach der Eingabe. Dadurch wird dieser Event das Programm nicht so stark blockieren.

Anschliessend kann man in dem Event den Text analysieren und die Werte in der Tabelle auslesen.

Ich nehme an die Werte in der Tabelle werden anhand der ID der Zelle lokalisiert.

Anmerkung: WPTools 8 Bundle enthält Komponenten names "TWPTableProducer" bzw "TWPTableProducerDB" welche eine Tabelle im Text anhand der Daten in einem TDataset erzeugt. Auch hier wird -optional- das Dataset upgedated bei Änderungen im Text. Für kleinere Datenbestände kann man damit eine Tabelle im Text generieren, die sich sofort drucken lässt, oder auch bereichsweise kopieren für die Weiterverarbeitung, z.b. in MS Word.

Viel Erfolg
Julian
WPCubed GmbH

himitsu 8. Feb 2018 13:48

AW: Mehrfachen Schleifenaufruf verhindern
 
"34,56" abarbeiten, ein Flag setzen, dass es schon gemacht wurde und dadurch die Schleife mit "12,35" abbrechen.

Natürlich vor der Schleife das Flad zurücksetzen-

jziersch 8. Feb 2018 14:08

AW: Mehrfachen Schleifenaufruf verhindern
 
Die Tabelle, also der Editor, sollte keine Messages generieren wenn Programmcode, also der code welcher Summenzeilen berechnet, die Tabelle ändert.

Das geht mit einem

Code:
if not BinInBerechnung then
try
  BinInBerechnung := true;

  sei fleissig
finally
  BinInBerechnung := false;
end;
Die Messages mit PostMessage absetzen - sonst wird der code sofort abgearbeitet, was nicht unbedingt gut für die Performance ist. Auch hier kann man sich merken, dass man bereits die PostMessage abgesetzt hat um dies dann nicht nochmal zu machen.

WPTools macht das intern sehr oft - sie StartUpdate() in unit WPCtrMemo.

sko1 8. Feb 2018 14:26

AW: Mehrfachen Schleifenaufruf verhindern
 
Danke für die vielen Denkanstöße!

Die beiden Hinweise betreffend ChangeSelection und Paint sind erst mal die wichtigsten, wobei ich .Paint mit Sicherheit probiert habe, genau so wie .Refresh, allerdings im OnChange-Event!

Dass ChangeSelection gefeuert wird, wenn man tippt, war mir bisher nicht bewusst, man lernt halt nie aus ;-)

Dann mach ich mich mal ans Ändern...

Ciao
Stefan

sko1 9. Feb 2018 05:57

AW: Mehrfachen Schleifenaufruf verhindern
 
Zitat:

for i := 1 to 100 do
begin
WPRichText1.ActiveParagraph.Append(IntToStr(i));
WPRichText1.ReformatAll;
WPRichText1.Paint;
Sleep(50);
end;
Funktioniert, ändert aber nach langen Tests an meinem eigentlichen Problem nichts:
Im obigen Code kommen die Änderungen aus dem Code, bei mir wird das erste eingetippte Zeichen jetzt sofort angezeigt (.Paint, ich hatte immer .Repaint probiert!) aber dann kommen weitere getippte zeichen erst an wenn der Schleifencode abgearbeitet ist!

Hier werden also scheinbar die Messages der getippten Zeichen "verzögert" weitergereicht!

Ich denke hier wird eine TList mit den zu sendenden Messages und ein Thread der sich um das Versenden kümmert, die einzige saubere Lösung sein!

Darf ich in s´dem Zusammenhang einfach mal fragen (da keine Erfahrung) was bei PostMessage passiert außer dass es keine Rückmeldung gibt?
Können Messages verloren gehen oder sich die Reihenfolge des Eingangs beim Empfänger ändern?

Ciao
Stefan

jziersch 9. Feb 2018 07:24

AW: Mehrfachen Schleifenaufruf verhindern
 
Hallo,

In meinem Test kommen bei dem Beispiel die Zeichen der Reihe nach. Evtl. gibt es da noch code in OnChange welcher daran was ändert.

Ich habe auch Paint in OnChange probiert, das geht auch.

Im Unterschied zu SendMessage, schreibt PostMessage die meldung in die Message loop und kehrt dann zurück. Ob die Meldung verarbeitet wird und wann, bekommt der Aufrufer nicht mit.

SendMessage ruft den MessageHandler sofort auf und kehrt zurück, wenn fertig.

>> Ich denke hier wird eine TList mit den zu sendenden Messages und ein Thread der sich um das Versenden kümmert, die einzige saubere Lösung sein!<<

Das hört sich kompliziert an. Letztendlich geht es doch darum die Tabelle nach einer Änderung auszulesen, die geänderten Werte in eine Datenbank zu schreiben und Summen zu bilden. Muss man dies denn für jeden Wert der sich ändert machen?

Ich meine es reicht dies zeitnah nach der Änderung zu machen, oder wenn der Anweder das Feld verlässt, CR drückt o.ä. Dann allerdings muss man alle Werte auslesen und die geänderten zurückschreiben. Nur die aktuelle Zelle zu überwachen erscheint mir keine gute Idee.

Wenn man nicht Werte in die Datenbank schreiben will, die nicht geändert wurden, kann man eine Liste mit Zellen (IDs) anlegen in OnChange welche bearbeitet werden. Immer wenn die Update Prozedur an der Reihe ist, kann sie diese Liste durchgehen und abarbeiten. Aus einem anderen Thread wird das nicht gehen, da von diesem kein Zugriff in WPTools möglich ist.

WPTools ist zwar threadsave, aber nur wenn es nicht für den Eingabe Modus erstellt wurde. Siehe Beispiele zur threadsave PDF erstellung.

Ich bin jetzt auf jeden Fall für ein paar Tage schlecht zu erreichen, der vorliegende Quellcode sollte aber einige Hilfestellungen bieten.

Grüsse,
Julian
WPCubed GmbH


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:53 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