2014-07-26 47 views
-1

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

这里是我的代码,我测试:

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. 
+0

然而,我们仍然不知道问题是什么。 “直接在线程之外终止线程”是什么意思? –

+0

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

+0

好的,这是一个好的开始。但是,你能修正上面的代码,以便它编译?你说它有效,但我们都看到证明它不起作用。 –

回答

0

当你调用TThread.Terminate(),它设置TThread.Terminated属性设置为true,并没有别的。您的TThread.Execute()代码有责任定期查看TThread.Terminated属性,并在其为True时正常退出。但是,在这种情况下,这是不可能的,因为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.