2015-01-04 13 views
1

tl; dr 버전 : WinForms 단추의 MouseDown 이벤트에서 소리를 재생하고 같은 단추의 MouseUp 이벤트에서 재생하지 못하게하려면 어떻게해야합니까?mouseUp 이벤트의 SoundPlayer를 중지하십시오.

중간급 C# dev 여기에서 간단한 Simon 복제본을 작성하려고했습니다.

사용자가 버튼을 클릭하는 동안에 만 색상이 지정된 버튼의 사운드가 재생되도록 노력하고 있습니다. (나는 "버튼"과 상호 교환 "타일"을 사용 모두 사용자가 양식에 누를 것이다 색깔의 버튼을 참조하십시오.) 나는 원래이 시도

:

public partial class frmMain : Form 
{ 
    private SoundPlayer soundPlayer; 

    private void btnGreenTile_MouseDown(object sender, MouseEventArgs e) 
    { 
     soundPlayer = new SoundPlayer(Properties.Resources.greenTileSound) 
     soundPlayer.Play(); 
    } 

    private void btnGreenTile_MouseUp(object sender, MouseEventArgs e) 
    { 
     soundPlayer.Stop(); 
    } 
} 

을하지만이 멈추지 않았다 MouseUp 이벤트는 MouseDown이 끝나지 않아 시작되지 않았기 때문에 소리가 들리지 않습니다 (누군가가 간단한 클릭보다 오랫동안 버튼을 누르고있는 경우에도 5 초 길이의 소리를 계속 재생 함). Luis Tellez가 언급 한 것처럼 SoundPlayer는 사운드를 새로운 스레드에서 재생하므로 ...이 코드가 지금 작동하지 않는 이유를 알 수 없습니다. 그것은 이는 MouseUp에 소리 재생을 중지하지 않고, 더 나은 그것은 "스레드가 실행되거나 메시지와 함께 ThreadStateException을 던져, 위의 코드와

public partial class frmMain : Form 
{ 
    private Thread soundThread = new Thread(new ParameterizedThreadStart(PlaySound)); 

    // Create stream objects for each sound (needed to allow SoundPlayer to use Resources) 
    private Stream greenTileSound = Properties.Resources.greenTilePress; 
    private Stream redTileSound = Properties.Resources.redTilePress; 
    private Stream yellowTileSound = Properties.Resources.yellowTilePress; 
    private Stream blueTileSound = Properties.Resources.blueTilePress; 

    public frmMain() 
    { 
     InitializeComponent(); 
    } 

    private void btnGreenTile_MouseDown(object sender, MouseEventArgs e) 
    { 
     soundThread.Start(greenTileSound); 
    } 

    private void btnGreenTile_MouseUp(object sender, MouseEventArgs e) 
    { 
     soundThread.Abort(); 
    } 

    // Have to use object as parameter because ParamterizedThreadStart() only takes object arguments 
    private static void PlaySound(object soundToPlay) 
    { 
     SoundPlayer soundPlayer = new SoundPlayer((Stream)soundToPlay); 
     soundPlayer.Play(); 
    } 
} 

:

그래서 나는 멀티 스레딩에보고하고이 시도 종료되었으며 재시작 할 수 없습니다. "

아마도이 코드를 작성하는 동안 멀티 스레딩에 대해서 배웠을 것입니다. 스레드가 시작될 때 호출하는 메서드 인 PlaySound()가 player (.wav 파일)가 누른 채색 된 단추에 해당하는 리소스로 soundPlayer에 매개 변수를 전달해야하므로 ParameterizedThreadStart를 사용해야합니다.

는 그때 ... 어쩌면 내가 soundThread.Suspend() 대신 soundThread.Abort()을 사용하려고하지만 사용되지 않습니다 일시 중단해야 생각

사람에게 소리를 얻기 위해 올바른 방향으로 날 지점 수 MouseUp에서 중지 하시겠습니까? 멀티 스레딩 작업이 필요합니까? 나는 내 문제가 논리로 내려 왔다고 생각하지만 완전히 붙어있다. 모든 도움에 감사드립니다! :)

부수적으로, 나는이 질문이나 뭔가가 아직 (적어도 Google 검색 또는 stackExchange 검색으로 찾을 수 없음) 묻지 않았 음에 놀랐습니다.

+0

나는 문제 (첫째, 비는 스레드 방식)을 재현하려고했으나 정확한 파일 위치를 SoundPlayer를 가리키는 것이 아니라 스트림을 사용하여를하고 그것을 잘 작동하므로 시도했습니다 스트림이 어떻게 작동하는지 살펴 보려면 문제가있을 수 있습니다. –

+0

스크래치는 스트림과도 작동합니다. 'Properties.Resources.greenTilePress'의 코드는 무엇입니까? –

+0

Properties.Resources.greenTilePress는 리소스 (.wav 파일)입니다. Visual Studio 프로젝트를 추가하여 EXE에 포함 시켰습니다. 귀하의 의견 후 다시 스레드가 아닌 접근 방식을 시도하고 효과가 (나는 문자 그대로 복사하고 여기에서 코드를 붙여 넣습니다). 나는 그것이 왜 작동하지 않았는지 전혀 모른다. 당신의 도움을 주셔서 감사합니다! –

답변

1

다른 스레드에서 play() 메서드가 실행되고 그 후에 다른 작업을 수행 할 수 있으며 실행해야하므로 첫 번째 방법의 문제점은 사용자가 생각한 것과 다른 것입니다.

Play 메서드는 새 스레드를 사용하여 사운드를 재생합니다. .wav 파일을 메모리에로드하기 전에 재생 을 호출하면 재생을 시작하기 전에 .wav 파일을로드해야합니다. LoadAsync 또는 Load 메서드를 사용하여 미리 .wav 파일을 메모리에로드 할 수 있습니다. .wav 파일 이 스트림 또는 URL에서 성공적으로로드 된 후 향후 SoundPlayer에 대한 재생 메서드를 호출하면 사운드 경로가 변경 될 때까지 .wav 파일 을 다시로드 할 필요가 없습니다. .wav 파일이 으로 지정되지 않았거나로드되지 않으면 Play 메서드가 기본 경고음을 재생합니다.

http://msdn.microsoft.com/en-us/library/system.media.soundplayer.play%28v=vs.110%29.aspx

+1

게시 된 코드에서 이유를 볼 수 있습니다. 정상적으로 작동한다는 것을 이해하면 GIT에서이 코드를 복제하고 테스트 해 볼 수 있습니다. –

+1

예 첫 번째 코드가 작동합니다. 나는 그것이 전에는 나에게 도움이되지 못했지만 나는 분명히 뭔가를 망쳤다. 시간을내어 도와 주셔서 대단히 감사합니다! –