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;