Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Problem mit TImage (https://www.delphipraxis.net/189605-problem-mit-timage.html)

calibra301 29. Jun 2016 08:14

Delphi-Version: 5

Problem mit TImage
 
Hallo,

habe ein komisches Problem...

Es geht um eine seit Jahren funktionierende Anwendung. Diese hate eine GUI mir einem TabSheet und mehreren Pages.
Auf den Pages sind munter Trackbars, Buttons und Images verteilt um Geräteparameter zu setzen.

Über eine Buttonleiste wird zwischen den Geräten umgeschaltet.
Beim Umschalten werden in einer Prozedur alle aktuellen Fader/Checkbox/Edit´s usw. in ein Array of Record gespeichert
und dann mit der neuen Geräteadresse die Werte wiedergeholt und Fader usw. gesetzt.
Unter anderem wird auch nach Daten aus dem Record auf 2 Images (auf verschiedenen Pages )mit einer Kurve gezeichnet.

Vorgehensweise ist immer die selbe. Wird ein Geräteparameter geändert wird "Data_to_Record " aufgerufen. Wird ein anderes Gerät
gewählt wird "Record_to_Data" aufgerufen.

Nun kam jemand auf die Idee man könnte die Änderungen doch auch per Smartphone machen. Die Daten kommen per UDP rein,
sind laut Debugging auch alle richtig und werden in den Record geschrieben. Klappt alles wunnebar mit einer Ausnahme:
Ist die Page mit dem zweitem Image aktiv und es wird die Routine aufgerufen die dieses Image mit den neuen Daten zeichnet wird das
Image weiss und ist quasi "weg".

Ändere ich die Daten wärend eine andere Page aktiv ist und schalte dann auf die richtige Page wird alles korrekt dargestellt.
Daten sind also richtig angekommen.

Mache ich den Aktualisierungsaufruf nicht in der Routine sondern später durch hin/zurückschalten auf ein anderes Gerät
gehts auch.

Nach dem das Image weiss ist ist es "weg" . Einfach nicht mehr erreichbar.
Ein zussätzlicher Button der einfach nur das Image schwarz füllt hat dann keine Funktion mehr.
Auch alle anderen Funktionen die das Image einst veränderten sind ohne Funktion. Es bleibt weiss bis zum Neustart.

Der Code ist sehr umfangreich. Aber im Grunde werden nur die Daten nun aus anderer Quelle gesetzt und der ewig funktionierende
Aktualisierungsaufruf geht gegen den Baum.

System ist Win 10 / XE8

Danke und Gruss
Calli

Bernhard Geyer 29. Jun 2016 08:18

AW: Problem mit TImage
 
Läuft die Kommunikation über UDP evtl. in einem eigenen Thread?

calibra301 29. Jun 2016 08:22

AW: Problem mit TImage
 
Hi,

UDP Server ist auf dem gleichem Form, Procedure ServerUDPRead in der gleichen Unit.

Gruss
Calli

Sir Rufo 29. Jun 2016 08:46

AW: Problem mit TImage
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1341475)
Läuft die Kommunikation über UDP evtl. in einem eigenen Thread?

Zitat:

Zitat von calibra301 (Beitrag 1341476)
UDP Server ist auf dem gleichem Form, Procedure ServerUDPRead in der gleichen Unit.

Also Ja :stupid:

Du darfst auf die Controls nur im MainThread zugreifen. Also benötigst du minimum eine
Delphi-Quellcode:
TThread.Synchronize
oder
Delphi-Quellcode:
TThread.Queue

calibra301 29. Jun 2016 09:03

AW: Problem mit TImage
 
Ups..

verstehe ich nicht aber danke für die Antwort.
Kannst du mir das bitte etwas näher erläutern ?
Unter einer Syncronisation kann ich mir ja etwas vorstellen aber wie mache ich das
und wo ? Sind ja wohl nicht einfach nur die Aufrufe..oder ?

Danke und Gruss
Calli.

Sir Rufo 29. Jun 2016 09:12

AW: Problem mit TImage
 
Erst mal in die Doku schauen Delphi-Referenz durchsuchenTThread.Synchronize / Delphi-Referenz durchsuchenTThread.Queue, das sollte die Frage beantworten.

calibra301 29. Jun 2016 09:45

AW: Problem mit TImage
 
Da reichts bei mir dann wohl nicht... :-(
Auc das was ich an Code-Beispielen ergoogelt hab leuchtet mir nicht ein.

Hab wie gesagt die Server-Komponente einfach aufs Form gepackt und die Funktion OnUDPRead benutzt..

Aus dem Quelltext:
Delphi-Quellcode:
procedure TForm1.ServerUDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var i:Integer;
    Buffer:TIDBytes;
    Settings:TMySettings;
begin
....

end;
Der Rest spielt sich alles unter "TForm1.xxx" ab.

Gruss
Calli
( der nun mal weiterwühlt.. )

Sir Rufo 29. Jun 2016 09:53

AW: Problem mit TImage
 
Ein simples Beispiel wäre z.B. das hier:
Delphi-Quellcode:
procedure TForm1.ServerUDPRead(AThread: TIdUDPListenerThread;
  const AData: TIdBytes; ABinding: TIdSocketHandle);
var i:Integer;
    Buffer:TIDBytes;
    Settings:TMySettings;
begin
 
  TThread.Synchronize( nil,
    procedure
    begin
      Edit1.Text := Length( AData );
    end );

end;

calibra301 29. Jun 2016 10:11

AW: Problem mit TImage
 
Brmpf...

habs nur abgeändert auf
Delphi-Quellcode:
begin

   TThread.Synchronize( nil,
     procedure
     begin
       i := Length( AData );
     end );

end;
und vor dem i:=Length... nen Breakpoint gesetzt.
Send ich nun was per UDP MÜSSTE er da doch anhalten...tut er aber nicht...

EDIT: Bei der Serverkomponente ist Threaded Event:=true;

Gruss
Calli

Sherlock 29. Jun 2016 10:44

AW: Problem mit TImage
 
Kurze Zwischenfrage zum Verständnis: Wieso ist die VCL-Ereignisbehandlungsroutine der UDP-Komponente als eigener Thread zu bewerten? Das klingt in meinen Ohren falsch.

Edith sah eben, es geht um Indy... carry on. Schön ist es dennoch nicht.

Sherlock

Sir Rufo 29. Jun 2016 11:04

AW: Problem mit TImage
 
Zitat:

Zitat von Sherlock (Beitrag 1341502)
Kurze Zwischenfrage zum Verständnis: Wieso ist die VCL-Ereignisbehandlungsroutine der UDP-Komponente als eigener Thread zu bewerten? Das klingt in meinen Ohren falsch.

Edith sah eben, es geht um Indy... carry on. Schön ist es dennoch nicht.

Mit INDY hat das nur nebensächlich etwas zu tun. Der Thread-Kontext in dem die Methoden aufgerufen werden wird nicht durch die Klasse festgelegt, sondern durch den Aufrufer der Methode. :wink:

Eine Server Komponente (idR für eine Verbindung zu 1+ Clients) läuft entweder sehr schlecht oder pro Client-Verbindung in einem Thread. Ob die Komponente jetzt von INDY oder wem auch immer ist, ist dabei egal :stupid:

Sherlock 29. Jun 2016 11:16

AW: Problem mit TImage
 
Ich will den Thread nicht "hijacken" man möge mich also bremsen/zurechtweisen/strafen.
In diesem Beispiel geht es um UDP. Je nach Komponente ist die Implementierung eines UDP-Servers Multithreading in Eigenverantwortung (zB Indy) oder in Komponentenverantwortung (zB ICS). Nach meinem Verständnis der VCL ist letzteres eher der "Delphi-way". Das "blutige" ist weggekapselt, der Entwickler muss sich keine Gedanken darum machen. Darum mein "ach, es ist ja Indy".

Sherlock

Sir Rufo 29. Jun 2016 11:20

AW: Problem mit TImage
 
Ich wollte nur vorbeugen, falls jetzt der Eindruck (bei wem auch immer) entsteht, man müsste nur etwas anderes als Indy nehmen und dann bräuchte man kein Synchronisieren :stupid:

calibra301 29. Jun 2016 11:26

AW: Problem mit TImage
 
Tja,

bei mir leider nix neues.
Wie gesagt, Komponente steht auf Treaded:=true

Verwende ich die "Syncroniz-Kapselung" wie in Sir Rufo´s Beispiel auf Seite 1 wird UDP Read nicht mehr
angesprungen.

calibra301 29. Jun 2016 12:40

AW: Problem mit TImage
 
Habs nur ein bisschen umgebaut:

Delphi-Quellcode:
procedure TForm1.ServerUDPRead(AThread: TIdUDPListenerThread;
   const AData: TIdBytes; ABinding: TIdSocketHandle);
begin

     TThread.Synchronize( nil,
     procedure
     begin
       setlength(Buffer,length(AData) );
       move(AData,Buffer,length(AData) );
       Do_Something;
     end );
end;
Nun wird hier nur der Empfangsbuffer in einen lokalen kopiert und dann in "Do Something"
ausgewertet.
Sende ich was per UDP hält das Programm in der Zeile TThread.Sync... einmal an
und dann nie wieder :-(

Sir Rufo 29. Jun 2016 13:30

AW: Problem mit TImage
 
Warum willst du die Auswertung synchronisiert vornehmen?

Die Ausgabe an die Controls muss synchronisiert erfolgen, die Auswertung, etc. eher nicht (das ist da wurscht) bzw. eher hinderlich, weil jetzt jeder Empfangsthread den MainThread sehr lange blockiert und dann stehen sich alle auf den Füßen rum.

Stell dir vor du bist der Chef und deine Mitarbeiter bearbeiten emails. Es darf immer nur einer mit dir sprechen.

Jetzt öffnet jeder Mitarbeiter eine email und sucht das Gespräch mit dir (wartet höflich bis er an der Reihe ist), um dir die ganze email vorzulesen ... und dir ganz zum Schluss mitteilt, ob die nun für dich relevant ist oder nicht.

Wäre es nicht günstiger von der Zeit und für deine Ohren, wenn jeder Mitarbeiter die email erst einmal still und heimlich vor sich hin liest und dir nur eine kurze Rückmeldung gibt (wenn es wichtig ist)?

Du versuchst gerade die ungünstige Variante

calibra301 29. Jun 2016 17:33

AW: Problem mit TImage
 
Hi Rufo,

Denke das Problem ist das ich die Vorgehensweise / dem Sinn der Syncronisierung nicht verstanden hab.
Bin nicht so der Crack der das schon jahrelang macht.
Bei Themen wie Cortex M0/M7 könnte ich eher helfen. Da unter einem RTOS Threadprioritäten zu verteilen
oder mit dem NVIC zu arbeiten finde ich wesentlich logischer.

Bisher war mein Gedanke das wenn ich "Threaded" aktiviere der Empfang mehr oder weniger
unabhängig vom Rest läuft und ich trotz UDP nix verpasse.
Nun kopiere ich mir den Empfangspuffer in einen lokalen und murkse dann weiter.

Gruss
Calli

Sir Rufo 29. Jun 2016 18:16

AW: Problem mit TImage
 
Das passiert ja auch alles threaded, aber wenn du dieses schöne Nebeneinander wieder durch eine Synchronisierung in ein Hintereinander presst, dann hat es sich eben mit dem Nebeneinander erledigt.

Hier ein kleines Minimal-Beispiel:
Delphi-Quellcode:
procedure WillBeCalledFromAThread( foo: TFoo );
var
  i:Integer;
begin

  // ** Im Thread

  // Ganz was Aufwändiges berechnen
  Sleep( 5000 );
  // unser Ergebnis
  i := 1;

  // Das Ergebnis in der Form anzeigen, das dürfen wir aber nur synchronisiert
  TThread.Synchronize( nil,
    procedure
    begin

      // ** Im MainThread

      // Berechnung hier?
      // Sleep( 5000 ); // <- würde das Programm für den Benutzer für 5 Sekunden blockieren
      // also doof, lieber vorher berechnen, da stört es nicht

      MyForm.ListBox.Items.Add( IntToStr( i ) );
    end);

  // ** Im Thread

  // nochwas machen?
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:49 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz