【问题标题】:How can I terminate thread directly outside of thread in delphi?如何在delphi中直接在线程之外终止线程?
【发布时间】:2014-07-26 20:04:13
【问题描述】:

我想通过单击按钮来终止线程。如果线程在没有用户中断的情况下正常工作是可以的,但有时用户需要中止线程,这就是用户如何中止线程的问题。

这是我测试的代码:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, mmsystem, ExtCtrls;

type
  TForm1 = class(TForm)
    Image1: TImage;
    procedure Image1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  end;

type
  hangth = class(TThread)
  private
    { Private declarations }
  protected
    procedure Execute; override;
    procedure play;
  end;

var
  Form1: TForm1;
  played: boolean;
  szalhang: hangth;

implementation

{$R *.dfm}

procedure hangth.play;
begin
  played := true;
  szalhang.Terminate;
end;

procedure hangth.Execute;
begin
  played := false;
  SndPlaySound(pchar('hang.wav'), SND_SYNC);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  played := true;
end;

procedure TForm1.Image1Click(Sender: TObject);
begin
  if played = true then begin
    szalhang := hangth.Create(true);
    szalhang.Resume;
  end else begin
    szalhang.Terminate();
    // here i want to terminate thread, but it doesn't want to be killed.
  end;
end;

end.

【问题讨论】:

  • 但我们仍然不知道问题是什么。 “直接在线程外终止线程”是什么意思?
  • 我想通过单击按钮来终止线程。如果线程在没有用户中断的情况下正常工作是可以的,但有时用户需要中止线程,这就是用户如何中止线程的问题。
  • 好的,这是一个好的开始。但是你能修复上面的代码以便编译吗?你说它有效,但我们都看到了它无效的证据。
  • 代码已重新附加。现在可以编译了。
  • 它没有编译,我做了修复让它编译并为你清理它。现在你能更清楚一点它是如何不工作的吗?它做了什么/没有做什么是你意想不到的?

标签: multithreading delphi kill


【解决方案1】:

当您调用TThread.Terminate() 时,它会将TThread.Terminated 属性设置为true,并且不执行任何其他操作。您的TThread.Execute() 代码有责任定期查看TThread.Terminated 属性并在它为True 时优雅地退出。但是,在这种情况下,这是不可能的,因为SndPlaySound() 正在阻塞线程,并且在SndPlaySound()SND_SYNC 模式运行时无法中断SndPlaySound()。您唯一的选择是使用 Win32 API TerminateThread() 函数来执行线程的暴力终止。

由于您显然需要更多地控制音频的播放,并检测音频何时播放完毕,那么SndPlaySound() 并不是满足您需求的最佳解决方案。你有一个TForm,你可以考虑使用Delphi的TMediaPlayer组件,例如:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, Vcl.MPlayer;

type
  MPlayerState = (mpsClosed, mpsOpened, mpsPlaying);

  TForm1 = class(TForm)
    Image1: TImage;
    MediaPlayer1: TMediaPlayer;
    procedure MediaPlayer1Notify(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Image1Click(Sender: TObject);
  private
    { Private declarations }
    State: MPlayerState;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm56.FormCreate(Sender: TObject);
begin
  State := mpsClosed;
  MediaPlayer1.FileName := 'C:\full path to\hang.wav';
end;

procedure TForm56.MediaPlayer1Notify(Sender: TObject);
begin
  case MediaPlayer1.Mode of
    mpStopped, mpPlaying:
      State := mpsOpened;
  end;
end;

procedure TForm1.Image1Click(Sender: TObject);
begin
  if State = mpsClosed then
  begin
    MediaPlayer1.Notify := False;
    MediaPlayer1.Wait := True;
    MediaPlayer1.Open;
    State := mpsOpened;
  end;

  if State = mpsOpened then
  begin
    MediaPlayer1.Notify := True;
    MediaPlayer1.Wait := False;
    MediaPlayer1.Play;
    if MediaPlayer1.Error = 0 then
      State := mpsPlaying
  end else
  begin
    MediaPlayer1.Notify := False;
    MediaPlayer1.Wait := True;
    MediaPlayer1.Stop;
    State := mpsOpened;

    MediaPlayer1.Notify := False;
    MediaPlayer1.Wait := True;
    MediaPlayer1.Close;
    State := mpsClosed;
  end;
end;

end.

【讨论】:

    猜你喜欢
    • 2011-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-10
    • 2015-12-21
    • 1970-01-01
    • 2012-05-11
    相关资源
    最近更新 更多