Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Thread mit Form-Aufruf (https://www.delphipraxis.net/46011-thread-mit-form-aufruf.html)

Bloodfire 16. Mai 2005 17:39


Thread mit Form-Aufruf
 
Hi!

Ich arbeite gerade an einem kleinen Netzwerkschach, welches auf folgendem beruht:

- Hauptform (primärer Thread) mit einer Userliste (PopUp-Menü: Privaten-Dlg öffnen / Schachbrett öffnen)

wenn nun entweder ein PrvDlg mit einem der User geöffnet werden soll, bzw. ein Schachbrett soll je ein neuer Thread ausgeführt werden. Das Problem dabei ist nun folgendes:

wenn ich FreeOnTerminate auf True stelle müsste ich mit ShowModal arbeiten, das wiederum aber die Hauptform deaktivieren würde und gegen das Prinzip des Projektes verstößt (da es simultanfähig sein sollte).

Seltsamerweise würde das mit ShowModal funktionieren, wenn ich meinen Aufruf der Schachbrettklasse direkt in den Execute-Abschnitt des Threads schreiben würde (ohne Synchronize), das widerum schlägt sich aber auf die Grafiken nieder, die dann, wenn man mit einem Fenster darüber fährt, verschwinden.

sähe dann so aus:

Delphi-Quellcode:
procedure TChessThread.Execute;
begin
   ChessBoard:=TChessBoard.Create;
   ChessBoard.Init(nil,0,0,AWidth,AHeight,APathFigures,AExtFigures,
     APathGraphics,AExtGraphics,APathFiles,ABoardIndex,AName);

   ChessBoard.ChessboardForm.ShowModal;

   ChessBoard.Free
end;
wenn ich jedoch (zugunsten der Grafik) das in eine extra Prozedur schriebe und diese synchronize (wofür das genau zuständig ist weiß ich immer noch nicht, aber ich sehe es an den Auswirkungen und in den Tuts wurde es empfohlen), sähe das so aus (und macht mein Hauptformular unzugängig):

Delphi-Quellcode:
procedure TChessThread.DoExecute;
begin
   ChessBoard:=TChessBoard.Create;
   ChessBoard.Init(nil,0,0,AWidth,AHeight,APathFigures,AExtFigures,
     APathGraphics,AExtGraphics,APathFiles,ABoardIndex,AName);

   ChessBoard.ChessboardForm.ShowModal;
end;

procedure TChessThread.Execute;
begin
  Synchronize(DoExecute);
end;
nun könnte ich ja diesen Code verwenden und ShowModal in Show umfunktionieren, dabei hab ich aber folgendes Problem:

da die maximale Schach-Brett Anzahl auf 5 limitiert sein soll, lasse ich außerhalb (Hauptform) eine Variable mitlaufen, welche sich bei einem Thrad Aufruf erhöht, und bei einem ThreadonTerminate-Ereignis erniedrigt (siehe: Code unten).

OnTerminate wird aber auch aufgerufen, wenn der Prozess nacher noch läuft (und nicht ge-.Free-t wurde), was dann hieße der Zähler bleibt auf 0, obwohl die Threads noch im Gange sind.

Noch dazu kommt das Problem, dass bei allen Varianten der Speicherbedarf (laut Task-Manager) immer nur ansteigt, auch wenn ich mit der ShowModal-Variante arbeite und den Speicher von meinem Schachbrett danach wieder befreie.

Woran kann das liegen?


Und eine Sache wäre dann noch: Wie kann ich überprüfen, ob mit einem der User schon ein Schachspiel läuft? (also alle aktiven Threads durchgehen?)


Hier noch der Aufrufcode (im Hauptformular):

Delphi-Quellcode:
procedure TMainAppSingle.OnPopUpItemClick(Sender: TObject);
var
  ACaption: String;
  AOppName: String;
const
  AHeight = 480;
begin
   if (UserList.ItemIndex<0)
     then exit;

   ACaption:=TMenuItem(Sender).Name;
   ACaption:=Copy(ACaption,3,length(ACaption)-2);

   AOppName:=Userlist.Items[Userlist.ItemIndex];

   if (ACaption='Chess') then
     begin
        inc(RunningChess);
        if (RunningChess>MaxThreads) then
          begin
             dec(RunningChess);
             exit;
          end
        else
          with TChessThread.Create(false,AOppName,AHeight*750 div 560,AHeight,
                 PathGraphics+'Figures\',ExtFigures,PathGraphics+'Peripher\',
                 ExtGraphics,PathFiles,2) do
            OnTerminate:=OnChessThreadClose;
     end
   else
   if (ACaption='PrvDlg') then
     begin
        inc(RunningDlgs);
        if (RunningDlgs>MaxThreads) then
          begin
             dec(RunningDlgs);
             exit;
          end
        else
          with TPrvDlgThread.Create(false,AOppName,200,300) do
            OnTerminate:=OnPrvDlgThreadClose;
     end;
end;

und zur Vervollständigung:

Delphi-Quellcode:
//--On-ChessThread-Close--------------------------------------------------------
procedure TMainAppSingle.OnChessThreadClose(Sender: TObject);
begin
   dec(RunningChess);
end;

//--On-PrvDlgThread-Close-------------------------------------------------------
procedure TMainAppSingle.OnPrvDlgThreadClose(Sender: TObject);
begin
   dec(RunningDlgs);
end;

jfheins 16. Mai 2005 17:47

Re: Thread mit Form-Aufruf
 
Erstmal Herzlich Willkommen inj der DP,

:arrow: VCL hat im Thread grundsätzlich nichts verloren :!:

Soweit ich das verstanden habe, erstellst du im Thread ein Formular, spätestens auf einem Multiprozessorsystem wird die Anwendung unbenutzbar.

Aber warum soll jedes Schachbrett uberhaupt einen neuen Thread bekommen, lass doch alles im Hauptthread auführen ;)

:arrow: synchronize() führt eine bestimmte Methode im Kontext des Hauptthreads aus - hier darfst du mit der VCL rumspielen, ohne was kaputt zu machen :zwinker:

Zu guter letzt möchte ich dir noch dieses Threading-Tutorial ans Herz legen:
http://www.luckie-online.de/Tutorial...mit_Delphi.pdf

Bloodfire 16. Mai 2005 17:57

Re: Thread mit Form-Aufruf
 
Du meinst ich soll zb. 5 Instanzen der Schachbrett-Klasse erstellen?

Würde das
a) meine einzelnen Spiele nicht verlangsamen? und
b) wie kann ich dann von außen (bei FormClose der Schachklasse) die Schachklasse selbst vom Speicher löschen? (die basiert bei mir nämlich auf TObject in dem sich eine TForm befindet)

(danke für den Tutorial-Tipp)


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