2014-07-26 49 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.