Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Thread Error (https://www.delphipraxis.net/1380-thread-error.html)

Daniel B 19. Nov 2002 19:56


Thread Error
 
Hallöchen,

ich hab ein programm das bis vor kurzem noch auf dem PC lief. Nachdem ich es nun auf dem Schlepptop kopiert habe, alles neu erzeugt und kompliziert habe, kommt es zum folgenden Fehler.

Thread Error: Der Parameter stimmt nicht (87)

Dies passiert wenn ich auf den Beenden Button klicke. In dem seiner Proz. steht nur Close;, sonst nichts.
klicke ich die Meldung weg und dann nochmal auf Beenden, so wird das Programm normal beendet. Beim Kompliozieren gibt es weder Hinweise, noch Meldungen. Was will mir der Fehler mitteilen?.
Vielen Dank.

Grüsse, Daniel :hi:

sakura 19. Nov 2002 22:05

:?:

Hast Du irgendwelche Sonderheiten im Programm (z.B. Multi-Thread), ist ja immerhin ein Threadfehler...


...:cat:...

Daniel B 19. Nov 2002 22:22

Delphi-Quellcode:
unit Hauptformular;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, CPort, StdCtrls, Buttons, Einstellungen, Info, Inifiles;

type
  TForm1 = class(TForm)
    GroupBox1: TGroupBox;
    GroupBox2: TGroupBox;
    ComPort: TComPort;
    MainMenu: TMainMenu;
    ButtonSX0auf0: TButton;
    ButtonSX1auf0: TButton;
    ButtonSX0auf1: TButton;
    ButtonSX1auf1: TButton;
    Datei: TMenuItem;
    Extras: TMenuItem;
    MenueEinstellungen: TMenuItem;
    Hilfe1: TMenuItem;
    MenueHilfe: TMenuItem;
    N1: TMenuItem;
    MenueInfo: TMenuItem;
    GroupBox3: TGroupBox;
    BitBtnEin: TBitBtn;
    BitBtnAus: TBitBtn;
    BitBtnSX0und1auf0: TBitBtn;
    BitBtnBeenden: TBitBtn;
    MenueBeenden: TMenuItem;
    MenueNeustart: TMenuItem;
    BitBtnSX0und1auf1: TBitBtn;
    procedure FormShow(Sender: TObject);
    procedure BitBtnEinClick(Sender: TObject);
    procedure BitBtnAusClick(Sender: TObject);
    procedure BitBtnSX0und1auf0Click(Sender: TObject);
    procedure BitBtnSX0und1auf1Click(Sender: TObject);
    procedure MenueNeustartClick(Sender: TObject);
    procedure MenueEinstellungenClick(Sender: TObject);
    procedure MenueInfoClick(Sender: TObject);
    procedure ButtonSX0auf0Click(Sender: TObject);
    procedure ButtonSX1auf0Click(Sender: TObject);
    procedure ButtonSX0auf1Click(Sender: TObject);
    procedure ButtonSX1auf1Click(Sender: TObject);
    procedure BitBtnBeendenClick(Sender: TObject);

  private
    { Private-Deklarationen }

  public
    { Public-Deklarationen }

  end;

var
  Form1: TForm1;
  CPPort: string;
  CPBaud: string;
//  CPForm: string;

implementation
{$R *.dfm}

procedure TForm1.FormShow(Sender: TObject);
//Befehle die beim Start ausgeführt werden
var
  ini: TIniFile;
begin
  if not (FileExists('SXSETZER.ini')) then //wenn die Datei noch nicht angelegt ist
  begin
    ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
    try //Standardwerte schreiben
      ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
      ini.WriteString('Einstellungen', 'Port', 'COM1');
      ini.WriteString('Einstellungen', 'Baud', '9600');
//      ini.WriteString('Einstellungen', 'Format', '2');
      CPPort := ini.ReadString('Einstellungen', 'Port', ''); //Standardwerte lesen und setzen
      CPBaud := ini.ReadString('Einstellungen', 'Baud', '');
//      CPForm := ini.ReadString('Einstellungen', 'Format', '');
    finally
      ini.Free; //Datei schliessen/freigeben
    end;
  end
  else if FileExists('SXSETZER.ini') then //falls Datei schon vorhanden
  begin
    ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
    try //Werte lesen
      CPPort := ini.ReadString('Einstellungen', 'Port', '');
      CPBaud := ini.ReadString('Einstellungen', 'Baud', '');
//      CPForm := ini.ReadString('Einstellungen', 'Format', '');
    finally
      ini.Free; //Datei schliessen/freigeben
    end;
  end;
  BitBtnBeenden.SetFocus;
  ComPort.Port := CPPort; //ComPort Port setzen
  ComPort.CustomBaudRate := StrToInt(CPBaud); //ComPort BaudRate setzen
  ComPort.Open;
end;

procedure TForm1.BitBtnEinClick(Sender: TObject);
//Gleis EIN
begin
  ComPort.WriteStr(#255#128);
end;

procedure TForm1.BitBtnAusClick(Sender: TObject);
//Gleis AUS
begin
  ComPort.WriteStr(#255#0);
end;

procedure TForm1.BitBtnSX0und1auf0Click(Sender: TObject);
//SX0 und SX1 auf 0 setzen
begin
  ComPort.WriteStr(#114#2);
end;

procedure TForm1.BitBtnSX0und1auf1Click(Sender: TObject);
//SX0 und SX1 auf 1 setzen
var
  i: integer;
begin
  for i := 128 to 231 do
  begin
    ComPort.WriteStr(#254#0 + chr(i) + #255);
    ComPort.WriteStr(#254#1 + chr(i) + #255);
  end;
end;

procedure TForm1.MenueNeustartClick(Sender: TObject);
//Neustart der Zentrale
begin
  ComPort.WriteStr(#114#0);
end;

procedure TForm1.MenueEinstellungenClick(Sender: TObject);
//Das Einstellungen-Fenster öffnen
begin
  Einst.ShowModal;
end;

procedure TForm1.MenueInfoClick(Sender: TObject);
//Das Info-Fenster öffnen
begin
  About.ShowModal;
end;

procedure TForm1.ButtonSX0auf0Click(Sender: TObject);
//Adressen 0 - 103 bei SX0 auf 0 setzen
var
  i: integer;
begin
  for i := 128 to 231 do
  begin
    ComPort.WriteStr(#254#0 + chr(i) + #0);
  end;
end;

procedure TForm1.ButtonSX1auf0Click(Sender: TObject);
//Adressen 0 - 103 bei SX1 auf 0 setzen
var
  i: integer;
begin
  for i := 128 to 231 do
  begin
    ComPort.WriteStr(#254#1 + chr(i) + #0);
  end;
end;

procedure TForm1.ButtonSX0auf1Click(Sender: TObject);
//Adressen 0 - 103 bei SX0 auf 1 setzen
var
  i: integer;
begin
  for i := 128 to 231 do
  begin
    ComPort.WriteStr(#254#0 + chr(i) + #255);
  end;
end;

procedure TForm1.ButtonSX1auf1Click(Sender: TObject);
//Adressen 0 - 103 bei SX1 auf 1 setzen
var
  i: integer;
begin
  for i := 128 to 231 do
  begin
    ComPort.WriteStr(#254#1 + chr(i) + #255);
  end;
end;

procedure TForm1.BitBtnBeendenClick(Sender: TObject);
begin
  ComPort.Close;
  Close;
end;

end.

sakura 19. Nov 2002 22:41

Zitat:

Zitat von Daniel B
Delphi-Quellcode:
procedure TForm1.BitBtnBeendenClick(Sender: TObject);
begin
  ComPort.Close;
  Close;
end;

Mal ne doofe Frage. Kann es sein, dass Du dass Programm am PC über den Button schliesst, am Laptop jedoch mit Alt+F4 oder anders? Zumindest scheint es Voraussetzung zu sein, dass Du es über den Button schliesst, damit der COM-Port geschlossen wird :warn: - Setze dass doch lieber in das OnClose Ereigniss.

Ansonsten kann ich keine Probleme erkennen.

jbg 19. Nov 2002 22:45

Was willst du eigentlich mit
Zitat:

Code:
ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));
try //Standardwerte schreiben
  ini := TIniFile.Create(ChangeFileExt(ParamStr(0), '.ini'));

bewirken? Ein Speicherleck?

Daniel B 19. Nov 2002 22:52

Zitat:

Zitat von sakura
Mal ne doofe Frage. Kann es sein, dass Du dass Programm am PC über den Button schliesst, am Laptop jedoch mit Alt+F4 oder anders? Zumindest scheint es Voraussetzung zu sein, dass Du es über den Button schliesst, damit der COM-Port geschlossen wird :warn: - Setze dass doch lieber in das OnClose Ereigniss.

Ich habe im Menü natürlich den MEnüpunkt Beenden. Im OI steht bei OnClick, die OnClick-Proz. des BitBtns.
Ich hab noch ein bisschen rumgespielt. Es hat was mit dem ComPort schliessen zutun. Jetzt wo alles im BitBtnClick drin ist, passiert es nur noch wenn ich es über den Menüpunkt beende. Wenn ich aber das CP.Close; in der OnClose drin habe, passiert es auch wenn ich auf den Button klicke.

Grüsse, Daniel :hi:

Daniel B 19. Nov 2002 22:54

Zitat:

Zitat von jbg
Was willst du eigentlich mit
Zitat:

geschnippt
bewirken? Ein Speicherleck?

Hoppala, hab ich wohl übersehen, das zweite Create muss natürlich raus. Danke. Wär vielleicht niemals aufgefallen. :shock:

Grüsse, Daniel :hi:

Christian Seehase 19. Nov 2002 23:57

Moin Daniel B,

solche Aufräumarbeiten beim Beenden sollten, zur Sicherheit, immer in's OnDestroy des Formulares.
OnClose und OnCloseQuery werden bei Application.Terminate nicht aufgerufen.

Daniel B 20. Nov 2002 00:02

Hallo Christian,

und wo ist der unterschied, ob ich mit Close und OnClose arbeite, oder mit Terminate und OnDestroy?

Grüsse, Daniel :hi:

Christian Seehase 20. Nov 2002 00:21

Moin Daniel,

wenn Du immer sicherstellst, dass OnClose auch aufgerufen wird ist der gibt's eigentlich keinen Unterschied.
Solltest Du aber auch nur mal ein Formular dynamisch erzeugen, und mit Free wieder freigeben hast Du den Salat, wenn Du Deine Aufräumarbeiten im OnClose erledigen willst. Das wird dann nämlich auch nicht aufgerufen.

Wenn man immer genau aufpasst, dass die belegeten Resourcen immer wieder sauber freigegeben werden spielt der Zeitpunkt natürlich keine Rolle, an dem das geschieht.

Ich halte es allerdings für eine Verringerung der Fehlerwahrscheinlichkeit, wenn man sich für so etwas an Stellen gewöhnt, die bei einem normalen Programmablauf auch garantiert aufgerufen werden.

Soll heissen:
Werden Resourcen belegt (z.B. durch Create, so es sich denn nicht um eine Komponente mit Angabe des Owners handelt), gehört als nächstes ein try/finally Block gesetzt.
Oder Resourcen werden in OnCreate/OnDestroy bzw. initialization/finalization Paaren belegt/freigegeben.

Es mag natürlich immer mal Ausnahmen von der Regel geben, aber wo dieses nicht zwingend notwendig ist, halte ich es für sinnvoll diese Regeln für saubere Programme einzuhalten.
Manchmal kann man auch feststellen, dass man ein strukturelles Problem mit seinem Programm hat, wenn sich so eine Regel nicht einhalten lässt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:49 Uhr.
Seite 1 von 2  1 2      

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