Hallo Leute,
ich habe ein merkwürdiges Problem dessen Ursache ich nicht finden kann und welches auch nicht reproduziebar ist, sondern scheinbar nur zufällig auftritt.
Gegeben ist folgende Situation: Ich habe ein Programm, welches über den
COM-Port mit einer Platine kommuniziert, auf welcher sich Leuchtdioden befinden, die Buchstaben anzeigen können. Das funktioniert auch. Über einen bestimmten Befehl kann man den Helligkeitsstatus der Platine auslesen, je heller es ist, desto heller leuchten die Leuchtdioden, damit man den angezeigten Text trotzdem lesen kann. Auch das funktioniert.
Das Programm fragt periodisch den Helligkeitsstatus des Geräts ab und wertet diesen aus. Die Abfragen werden in einem Thread gemacht, da die Antwort des Gerätes manchmal nicht sofort kommt.
Die Werte liegen zwischen null und 65535, wobei null 0% und 65535 100% entspricht. In Abb. eins (Siehe Anhang) wird der aktuelle Wert als rote Linie dargestellt, die letzten fünf als Graue. Die Werte stehen oben links, oben rechts steht die Anzahl der Abfragen, sowie die Uhrzeit der letzten Abfrage. In Abb. zwei wird der Verlauf dargestellt, jede rote Linie steht für eine Abfrage. Die Werte die in den Labels sind die Gleichen wie in Abb. eins, und nur zu Testzwecken nochmals aufgeführt, denn:
Das Problem ist, dass das Programm manchmal aufhört, Abb. eins zu aktualisieren. Dies tritt nur ab und zu auf, mal öfter mal seltener, heute bisher zweimal, gestern nur einmal und vorgestern relativ häufig. Zunächst dachte ich, dass der Thread Probleme macht, dies ist aber nicht so, denn die Labels und Abb. zwei werden nach wie vor richtig aktualisiert.
Hier erstmal meine Threadklasse mit Erläuterung:
Delphi-Quellcode:
TBrighnessValuesThread = class (TThread)
private
FLDP1Controller: TLDP1Controller; //Die Klasse, die sich um die Kommunikation mit dem Gerät kümmert
//Es wird zunächst alles auf ein TBitmap gemalt, FBuffer ist für Abb. eins und FBufferCurve ist für Abb. zwei
FBuffer: TBitmap;
FBufferCurve: TBitmap;
//Die Images werden im Konstruktor übergeben
FImage: TImage; //Abb. eins
FCurveImage: TImage; Abb. zwei
//[...] (Ein paar für dieses Problem unwichtige Felder)
//Die Labels, die zusätzlich die Werte anzeigen
FLabels: TLabelArray;
//Diese Prozedur sorgt dafür, dass die bemalten Buffer auf die Images übertragen werden (Wird mit synchronize aufgerufen)
procedure BufferOnImage;
protected
//Dürfte klar sein ;-)
procedure Execute; override;
public
//[...] Ein paar Properties
//Der Konstruktor, hier werden die wichtigen Parameter wie
constructor Create(ALDP1Controller: TLDP1Controller;
AImage,ACurveImage: TImage; const AUnitNumber: byte; ASteps: integer);
reintroduce;
destructor Destroy; override;
end;
Die Execute Methode sieht (gekürzt) wie folgt aus:
Delphi-Quellcode:
procedure TBrighnessValuesThread.Execute;
var
Values: TBrightnessStateStruct; //Dort werden die ausgelesenen Werte reingeschrieben
hlp: double;
Last5Values: Array [0..4] of TBrightnessStateStruct; //Hier
i: Integer;
Counter: integer;
begin
inherited;
//[...] Ein bisschen Initialisierungskram
//Hauptschleife
while not Terminated do
if FLDP1Controller.Connection.Connected
then
begin
//[...] Zunächst mal neue Daten holen und in Values schreiben
//Pseudocode: Values := GetDaten;
inc(Counter);
//Altes Bild löschen und Rahmen zeichnen und Zahl und Zeit
FBuffer.Canvas.Rectangle(0,0,FBuffer.Width,FBuffer.Height);
FBuffer.Canvas.TextOut(FBuffer.Width-30,10,inttostr(Counter));
FBuffer.Canvas.TextOut(FBuffer.Width-50,25,FormatDateTime('hh:nn:ss',now));
//Die letzten 5 Werte zeichnen, in grau
FBuffer.Canvas.Font.Color := $CCCCCC;
FBuffer.Canvas.Pen.Color := $DDDDDD;
for i := 4 downto 0 do
begin
//Prozentwert ausrechnen
hlp := 100/65535*Last5Values[i].sensor_val;
//Und aufs Bild schreiben
FBuffer.Canvas.TextOut(10,25+i*15,FloatToStrF(hlp,ffFixed,10,2)+' % ('+inttostr(Last5Values[i].sensor_val) +')');
//Und auch in die Labels!
FLabels[i+1].Caption := FloatToStrF(hlp,ffFixed,10,2)+' % ('+inttostr(Last5Values[i].sensor_val)+') | '+inttostr(Last5Values[i].lststrom)+'/'+inttostr(Last5Values[i].solistrom);
//Linie Zeichnen
FBuffer.Canvas.MoveTo(1,FBuffer.Height-Trunc(hlp/100*FBuffer.Height));
FBuffer.Canvas.LineTo(FBuffer.Width-1,FBuffer.Canvas.PenPos.Y);
end;
//Und jetzt noch den aktuellen Wert berechnen und ausgeben
FBuffer.Canvas.Pen.Color := clred;
FBuffer.Canvas.Font.Color := clred;
hlp := 100/65535*Values.sensor_val;
FBuffer.Canvas.TextOut(10,10,FloatToStrF(hlp,ffFixed,10,2)+' % ('+inttostr(Values.sensor_val)+')');
FLabels[0].Caption := FloatToStrF(hlp,ffFixed,10,2)+' % ('+inttostr(Values.sensor_val)+') | '+inttostr(Values.lststrom)+'/'+inttostr(Values.solistrom);
FBuffer.Canvas.MoveTo(1,FBuffer.Height-Trunc(hlp/100*FBuffer.Height));
//Wert Zeichnen
FBuffer.Canvas.Pen.Color := clred;
FBuffer.Canvas.LineTo(FBuffer.Width-1,FBuffer.Canvas.PenPos.Y);
FBuffer.Canvas.Pen.Color := 0;
//Bilder auf Form übertragen
Synchronize(BufferOnImage);
//Werte verschieben
for i := 3 downto 0 do
begin
Last5Values[i+1] := Last5Values[i];
end;
Last5Values[0] := Values;
end;
end;
Das Zeichnen von Abb. zwei hab ich hier jetzt mal rausgelassen, da dort keine Probleme auftreten.
Die Sache ist, dass er die ganzen Zeichenroutinen durchgeht, auch wenn das Bild nicht aktualisisert wird. Die Labels bekommen exakt die gleichen Werte wie das Bild, aber die Lables werden weiterhin aktualisiert, genau wie Abb. zwei. Es kann also eigentlich nur daran liegen, dass er das Bild nicht mehr auf das Image überträgt, aber
WARUM? Es tritt kein Fehler auf, und die Execute Methode läuft genauso wie immer durch. Wie kommt es also, dass
NUR Abb. eins nicht weiter gezeichnet wird? Vor allem da dies absolut unregelmäßig auftritt...
Mein Kopf raucht schon
Ich hoffe ich habe alle wichtigen Informationen gegeben und dass mir jemand einen Tipp geben kann...
danke schonmal,
Ritsch