Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi "Ein Aufruf einer Betriebssystemfunktion ist fehlgeschlagen" (https://www.delphipraxis.net/62744-ein-aufruf-einer-betriebssystemfunktion-ist-fehlgeschlagen.html)

MStoll 8. Feb 2006 21:31


"Ein Aufruf einer Betriebssystemfunktion ist fehlgeschl
 
Hi @all.

Ich habe in einem StringGrid eine Tabelle mit 21 Zeilen und 11 Spalten. Die Daten werden mindestens jede Sekunde von einem Thread (heißt: "tliste") aktualisiert. Mit mindestens jede Sekunde meine ich, dass der Thread "tliste" in der Regel jede Sekunde aktualisiert, wenn er allerdings von dem Hauptthread dazu animiert wird zu aktualisieren, so tut er das sofort. Code wie folgt:

Delphi-Quellcode:
procedure tliste.execute;
var error_msg : string;
    t : integer;
begin
     stern_an := true;
     exec := false;

     repeat
       begin
          try
               zeige_alle_listen;

               t := gettickcount;
               while gettickcount - t < 1000 do
               begin
                    Sleep(10);
                    if exec then
                    begin
                         zeige_alle_listen;
                         exec := false
                    end
               end;
               stern_an := not (stern_an)
          except on e: exception do
          begin
               error_msg := 'Fehler beim Aktualisieren der Listen'+CHR(13)+CHR(10)+e.Message+CHR(13)+CHR(10)+'Prozedur "tliste.execute" in "uAusgabeliste"';
               save_err(error_msg)
          end
          end;
     end
     until terminated
end;
Dabei ist die Prozedur "zeige_alle_listen" diejenige, die die Daten aktualisiert. "Exec" ist eine Boolean-Variable des Threads, die vom Hauptthread auf "true" gesetzt wird, damit der Thread "tliste" sofort (d.h. wie ihr erkennen könnt max. 10ms später ;)) aktualisiert. Gezeichnet wird das StringGrid per OwnerDraw. Funktioniert soweit auch wunderbar und nach außen hin fehlerfrei. Allerdings sehe ich in meiner Datei "errors.log" (So heißt das Log-File für sämtliche "unerwartete" Exceptions) ab und zu die Fehlermeldung "Ein Aufruf einer Betriebssystemfunktion ist fehlgeschlagen".

Ich habe jedoch keine Ahnung, was diese bedeutet bzw. wo sie genau herkommen könnte. Debuggen ist auch schwierig, da die Meldung nur sporadisch auftritt.
Wäre dankbar, wenn mir jmd. helfen könnte oder es zumindest versucht. Wenn nötig, kann ich euch noch die Prozedur, die die Daten aktualisiert und die, die sie zeichnet, posten.

Gruß
Michael

zer00 8. Feb 2006 21:40

Re: "Ein Aufruf einer Betriebssystemfunktion ist fehlge
 
Schreibe die "Update-Methode" zeige_alle_listen einmal so Synchronize(zeige_alle_listen).

grz zer00

MStoll 8. Feb 2006 21:55

Re: "Ein Aufruf einer Betriebssystemfunktion ist fehlge
 
Erstmal Danke für die Hilfe!

Das funktioniert auch soweit. Nun meine Frage:
Kann es nun sein, dass meine Anwendung für den zugegebenermaßen kurzen Moment, in dem das Synchronize(zeige_alle_listen) aufgerufen wird, blockiert?

Bis jetzt habe ich zwar nichts davon gemerkt, allerdings ist dies ein Teil einer Zeitnahme-Anwendung, in der man über Stunden teilweise schnell Zahlen in ein Edit tippen muss. Und dies teilweise blind. Da wäre es ungünstig, wenn man zufällig in dem Moment der Aktualisierung der Listen eine Zahl tippt, die Anwendung aber durch die Aktualisierung blockiert wäre und evtl. das Zeichen "verschluckt".

Aus diesem Grunde hab ich das bisher ohne Synchronize gemacht, da ich jeglichen Zugriff auf diese Stringlist allein über den Thread "tliste" erledigt habe, damit dies komplett im Hintergrund passiert und keine Auswirkungen auf den Rest des Programms hat.

Kennst du oder jemand anderes solche Auswirkungen? Ich mache mir deswegen Sorgen, weil der Vorgänger dieses Programms ein DOS-Programm war und dies hat, da DOS ja nur eine einzige Aktion "gleichzeitig" zulässt, bei der Ausführung einer "Hintergrund"-Aktion so blockiert, dass für diesen Moment keine Eingabe möglich war und evtl. getippte Zeichen "verschluckt" wurden. Befürchte nun auf Grund des "Synchronize"-Aufrufes ähnliche Auswirkungen. Lasse mich aber gerne eines Besseren belehren.

zer00 8. Feb 2006 22:04

Re: "Ein Aufruf einer Betriebssystemfunktion ist fehlge
 
Ja da hast Du recht, durch den Aufruf von Synchronize wird der Thread kurzzeitig verlassen.
So viel ich weiss ist der direkte zugriff auf die VCL aus einem Thread der vom Object TThread abgeleitet ist nicht möglich.
Möchte hier aber nicht auf meine Meinung beharren.

grz zer00

MStoll 8. Feb 2006 22:15

Re: "Ein Aufruf einer Betriebssystemfunktion ist fehlge
 
Das Update hat folgendes gemacht:

StringGrid wird geleert. Habe dazu eigens eine Ableitung von TStringGrid gemacht, die ne Prozedur clear_nf hat, die alle Zellen bis RowCount/ColCount leert abgesehen von den FixedRows/FixedCols.
Dann werden die Zellen wieder neu mit Daten aus einem Array gefüllt.

Hat im Prinzip ja auch funktioniert. Der Anwender hat von keinem Fehler etwas mitbekommen und diese Meldung kam ja auch nur sporadisch. Ich weiß eben nicht, was sie mir sagen will.


Alle Zeitangaben in WEZ +1. Es ist jetzt 20:55 Uhr.

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