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 Thread hängt wenn Listview Eintrag bekommt (https://www.delphipraxis.net/117423-thread-haengt-wenn-listview-eintrag-bekommt.html)

Piro 17. Jul 2008 22:08


Thread hängt wenn Listview Eintrag bekommt
 
Guten Abend,

ich habe ein Thread-Verständnis-Problem. Mein Programm hat in einem ListView mehrer Computer, welche alle 30 Sekunden auf Erreicgbarkeit geprüft werden. Diese erfolgt in Thread. Das Ergebnis wird an das ListView zurückgeliefert. Das funktioniert auch alles einwandfrei. Bloß wenn ich zur Laufzeit einen neuen Computer hinzufüge, kommt eine Fehlermeldung (ListIndex überschreitet das Maximum). Schließe ich das Program und starte es erneut, funktioniert es wieder. Wenn man EInträge löscht funktioniert auch alles. Was einer warum?

Mein Thread
Delphi-Quellcode:
...
procedure MyThread.Execute;
begin
 CoInitialize(nil);
 try
   if art = 'CheckServerStatus' then
     CheckServerStatus;

   if art = 'ServerStatusToXML' then
     //ServerStatusToXML;
 except
    on e: exception do begin
      // mache hier irgendetwas mit dem Fehler.
    end;
 end;
 CoUnInitialize();
end;
...
procedure MyThread.CheckServerStatus;
begin
 if IsHostAlive(Server) = True then
 begin
   frm_main.lv_server.Items[lvid].ImageIndex := 1;    //Server Online
   if (status = '2') and (frm_main.FirstStart = False) then
     frm_main.lv_server.Items[lvid].SubItems[1] := '1' //Server Online
   else
     frm_main.lv_server.Items[lvid].SubItems[1] := '';
 end
 else
 begin
   frm_main.lv_server.Items[lvid].ImageIndex := 2; //Server Offine
   if (status = '1') and (frm_main.FirstStart = False) then
     frm_main.lv_server.Items[lvid].SubItems[1] := '2' //Server Online
   else
     frm_main.lv_server.Items[lvid].SubItems[1] := '';
 end;
end;
lvid ist richtig aber nach dem Hinzufügen, kommt beim ersten Benutzer der Fehler. Warum? Mit Synchronize kommt der gleiche Fehler. Was läuft da falsch? Planlos, ich hoffe auf eine Idee.

Meine Aktualisierungsroutine
Delphi-Quellcode:
procedure Tfrm_main.CheckServerStatus;
var
 i     : Integer;
 Thread : MyThread;
begin
 for i := 0 to lv_server.Items.Count - 1 do
 begin
   Thread                := MyThread.Create(True);
   Thread.art            := 'CheckServerStatus';
   Thread.lvid           := i; //ListView ItemIndex
   Thread.server         := lv_server.Items[i].Caption;
   Thread.status         := IntToStr(lv_server.Items[i].ImageIndex);
   Thread.FreeOnTerminate := True;
   Thread.Resume;
 end;
 lbl_overview_servercheck.Caption := FormatDateTime('dd. mmmm yyyy hh:nn:ss', now);
end;

NickelM 17. Jul 2008 22:11

Re: Thread hängt wenn Listview Eintrag bekommt
 
procedure Tfrm_main.CheckServerStatus;
var
i : Integer;
Thread : MyThread;
begin
for i := 0 to lv_server.Items.Count - 1 do
begin
Thread := MyThread.Create(True);
Thread.art := 'CheckServerStatus';
Thread.excute;
Thread.lvid := i; //ListView ItemIndex
Thread.server := lv_server.Items[i].Caption;
Thread.status := IntToStr(lv_server.Items[i].ImageIndex);
Thread.FreeOnTerminate := True;
Thread.Resume;
end;
lbl_overview_servercheck.Caption := FormatDateTime('dd. mmmm yyyy hh:nn:ss', now);
end;

Piro 17. Jul 2008 22:13

Re: Thread hängt wenn Listview Eintrag bekommt
 
Was soll das bringen? Das kennt er so nicht und kann damit nichts anfangen.

Bernhard Geyer 17. Jul 2008 22:20

Re: Thread hängt wenn Listview Eintrag bekommt
 
Autsch! In einen Thread auf ein Oberflächencontrol zugreifen. Das muss ja irgendwo krachen!
Wird denn ab und zu der Kommentar gelesen der in der neuen Unit mit der Thread-Klasse am Anfang steht :gruebel:

Assertor 17. Jul 2008 22:22

Re: Thread hängt wenn Listview Eintrag bekommt
 
Hi,

also das sieht bisher ja ziemlich chaotisch aus. Und @NickelM: Execute wird vom Thread selbst aufgerufen. Sonst würde das ja auch nicht im Thread-Kontext ablaufen, sondern innerhalb des Caller-Threads, sprich hier der VCL-Mainthread.

@daywalker: Wenn Du selbst schon Synchronize erwähnst, weißt Du ja auch das ein Zugriff auf VCL-Objekte immer synchronisiert erfolgen muß. Die ListView ist bestimmt nicht threadsafe...

Bau entsprechende interne Variablen und Properties in den Thread ein, die Werte annehmen und entsprechende synchronisierte Callback-Methoden, um die Informationen an die Oberfläche zurückzugeben.

Wenn nur am Ende zurückgegeben werden soll, kannst Du das im OnTerminate-Ereignis erledigen, da dieses im Kontext des Aufrufers, also hier des Mainthreads, erfolgt.

Gruß Assertor

@Bernhard: Du bist aber auch wieder schnell... ;)

Piro 17. Jul 2008 22:30

Re: Thread hängt wenn Listview Eintrag bekommt
 
Vielen Dank für die Hinweise. Kenne mich mit Threads noch nicht so aus. Deshalb so chaotisch. Hatte Synchronize weggelassen, da der Fehler auch kam. Ich versuch es mal mit dem OnTerminate Event.

Dank.

Sven

Piro 17. Jul 2008 22:44

Re: Thread hängt wenn Listview Eintrag bekommt
 
Das OnTerminate Event habe ich eingebaut aber mit der Variableübergabe klappt es nicht so wirklich. Würdet ihr mir etwas mehr dazu sagen?

Delphi-Quellcode:
procedure Tfrm_main.OnThreadTerminate(Sender: TObject);
begin
 ShowMessage('Am Ende');
end;

procedure Tfrm_main.CheckServerStatus;
var
 Thread : MyThread;
begin
 for i := 0 to lv_server.Items.Count - 1 do
 begin
   Thread                := MyThread.Create(True);
   Thread.art            := 'CheckServerStatus';
   Thread.server         := lv_server.Items[i].Caption;
   Thread.FreeOnTerminate := True;
   Thread.OnTerminate    := OnThreadTerminate;
   Thread.Resume;
 end;
 lbl_overview_servercheck.Caption := FormatDateTime('dd. mmmm yyyy hh:nn:ss', now);
end;
Wo müssen jetzt die Variablen hin damit ich sie im OnThreadTerminate verwenden kann?

Vielen Dank.

sirius 18. Jul 2008 08:14

Re: Thread hängt wenn Listview Eintrag bekommt
 
Als Felder in deinen Thread (bzw, dann als public properties).

Piro 18. Jul 2008 12:19

Re: Thread hängt wenn Listview Eintrag bekommt
 
Ich steige da immer noch nicht durch. Habe die Variabeln gesetzt aber ich kann nicht darauf zugreifen.

Thread Unit:
Delphi-Quellcode:
type
  MyThread = class(TThread)
  private
    { Private-Deklarationen }
  protected
    procedure Execute; override;
    procedure CheckServerStatus;
  public
    { Public-Deklarationen }
    art         : String;
    status      : String;
    lvid        : Integer;
  end;
...
procedure MyThread.Execute;
begin
 CoInitialize(nil);
 try
   if art = 'CheckServerStatus' then
     CheckServerStatus;
 except
    on e: exception do begin
      // mache hier irgendetwas mit dem Fehler.
    end;
 end;
 CoUnInitialize();
end;

procedure MyThread.CheckServerStatus;
begin
 if IsHostAlive(Server) = True then
   status := '1' //Server Online
 else
   status := '2'; //Server Online
end;
Meine Main Unit:
Delphi-Quellcode:
procedure Tfrm_main.OnThreadTerminate(Sender: TObject);
begin
 ShowMessage(MyThread.status); // Fehler: Methodenbezeichner erwartet. Welcher soll das sein?
end;

procedure Tfrm_main.CheckServerStatus;
var
 i     : Integer;
 Thread : MyThread;
begin
 for i := 0 to lv_server.Items.Count - 1 do
 begin
   Thread                := MyThread.Create(True);
   Thread.art            := 'CheckServerStatus';
   Thread.lvid           := i;
   Thread.server         := lv_server.Items[i].Caption;
   Thread.FreeOnTerminate := True;
   Thread.OnTerminate    := OnThreadTerminate;
   Thread.Resume;
 end;
 lbl_overview_servercheck.Caption := FormatDateTime('dd. mmmm yyyy hh:nn:ss', now);
end;
Fehler beim Kompilieren. Siehe OnThreadTerminate Prozedure.


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