Announcement

Collapse
No announcement yet.

Thread-Ausführung abbrechen

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Thread-Ausführung abbrechen

    Hallo,
    wie breche ich die Ausführung eines Threads ab (z.B. wenn's dem User zu lange dauert)?
    Gegeben sei der folgende Pseudocode ( (c) Andreas Kosch):
    procedure TZweiterThread.Execute;
    begin
    Suche initialisieren;
    Suche starten;
    while Datei gefunden do
    Synchronize(Suchergebnis);
    SucheNächsteDatei;
    end;
    Synchronize(Suche_ist_zu_Ende);
    end;

  • #2
    Hallo,

    der Aufruf der TThread-Methode <b>Terminate</b> setzt nur die Eigenschaft <b>Terminated</b>, so dass der Thread in der <b>Execute</b>-Methode diesen Wert in eigener Regie überwachen muss und falls notwendig, sich beendet. In der WHILE-Schleife muss also nur diese Eigenschaft ausgewertet werden, um die Schleife verlassen zu können. Das Ende des Threads ist dann mit dem Verlassen der Methode Exceute identisch. Wenn FreeOnTerminate ebenfalls aktiviert wurde, wird dabei sogar die TThread-Nachfolgerinstanz zerstört

    Comment


    • #3
      Hallo, <p>
      Was ich noch nicht verstanden habe, ist: Wo kann ich die Terminate-Methode des Threads aufrufen?
      <p> Hier ein kleines Beispiel: </p>
      <pre>
      procedure TTestThread.Execute;
      var
      I: Integer;
      begin
      FreeOnTerminate := True;
      for I := 1 to 2000000 do
      begin
      While not Terminated do
      begin
      Inc(Answer, Round(Abs(Sin(Sqrt(I)))));
      Synchronize(GiveAnswer); //GiveAnswer zeigt das Ergebnis an
      end;
      end;
      end;
      </pre>

      <p>Die Execute-Methode befindet sich in einer separaten Unit, der Thread wird aus der MainForm so aufgerufen:</p>

      <pre>
      procedure TMainForm.Button1Click(Sender: TObject);
      begin
      TTestThread.Create(False);
      end;
      </pre>

      Wenn ich in der MainForm jetzt versuche

      <pre>
      procedure TMainForm.StopBtnClick(Sender: TObject);
      begin
      TTestThread.Terminate;
      end;
      </pre>
      dann mault der Compiler: "Diese Form des Methodenaufrufs ist nur für Klassenmethoden erlaubt." Weiter reicht mein Latein nicht..

      Comment


      • #4
        Hallo,

        anstelle <i>TTestThread.Create(False);</i> aufzurufen und so auf das Handle des Threads zu verzichten, muss das Hauptformular eine Variable für die TThread-Instanz vorsehen. Das könnte zum Beispiel so aussehen (TOnCreateThread ist dabei der TThread-Nachfolger):
        <pre>
        type
        TFormMain = class(TForm)
        StatusBar1: TStatusBar;
        ProgressBar1: TProgressBar;
        BitBtnHelp: TBitBtn;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure BitBtnHelpClick(Sender: TObject);
        private
        { Private-Deklarationen}
        FOnCreateThread : TOnCreateThread;
        public
        { Public-Deklarationen}
        end;

        var
        FormMain: TFormMain;

        implementation

        {$R *.DFM}

        procedure TFormMain.FormCreate(Sender: TObject);
        begin
        FOnCreateThread := TOnCreateThread.Create(ProgressBar1);
        end;

        procedure TFormMain.FormDestroy(Sender: TObject);
        begin
        if Assigned(FOnCreateThread) then
        begin
        FOnCreateThread.Terminate;
        FOnCreateThread.WaitFor;
        end;
        end;
        </pre>
        Der Rückgabewert von TThreadXYZ.Create wird in dem privaten Objektfeld des Hauptfensters zwischengespeichert, so dass im Fall des Abbruchs durch den Benutzer die TThread-Methoden <b>Terminate</b> und <b>WaitFor</b> aufgerufen werden können.
        &#10

        Comment


        • #5
          Hi

          <pre>

          if Assigned(FOnCreateThread) then
          begin
          FOnCreateThread.Terminate;
          FOnCreateThread.WaitFor;
          FOnCreateThread := nil; // !!
          end;

          </pre>

          Wäre eine gute Ergänzung wenn FOnCreateThread.FreeOnTerminate := True; gesetzt wird. Dadurch enthält FOnCreateThread IMMER einen gültigen Wert, also "nil" oder gültiges ThreadObject.
          Man kann auch das FOnCreateThread.OnTerminate Event nutzen um die Variable zurückzusetzen. Wird NICHT so vorgegangen kann Assigned(FOnCreateThread) true zurückliefern obwohl kein gültiges Object drinsteht.

          Gruß Hage

          Comment

          Working...
          X