2015-01-04 7 views
1

tl; dr версия: Как начать воспроизведение звука в событии MouseDown кнопки WinForms и остановить его от воспроизведения в событии MouseUp той же кнопки?Stop SoundPlayer on mouseUp event

Промежуточный 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 воспроизводит звук на нем нового потока ... поэтому я понятия не имею, почему этот код не работает сейчас.

Так что я посмотрел в многопоточность и попытался это:

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(); 
    } 
} 

С кодом выше, это не останавливает воспроизведение звука на MouseUp, и даже лучше бросает ThreadStateException с сообщением «Тема работает или он не может перезагрузиться ».

Как вы, вероятно, можете сказать, я только что узнал о многопоточности при попытке написать этот код. Я должен использовать параметр ParameterizedThreadStart, потому что метод, который он вызывает при запуске потока, PlaySound(), должен передать параметр soundPlayer с ресурсом, соответствующим цветной кнопке, которая была нажата проигрывателем (файл .wav).

Я тогда подумал может быть, я должен попытаться использовать soundThread.Suspend() вместо soundThread.Abort() но Приостановка осуждается ...

Может кто-нибудь мне точку в правильном направлении, чтобы получить звук на остановить MouseUp? Нужно ли мне работать с многопотоком? Я думаю, что моя проблема сводится к логике, но я полностью застрял. Спасибо за помощь! :)

В качестве побочного примечания я удивлен, что этот вопрос или что-то подобное не было задано (по крайней мере, я не смог найти его с поисковыми запросами Google или поисками в стеке).

+0

Я пытался воссоздать вашу проблему (первый, не нарезкой подход), но сделал это, указывая SoundPlayer на точное местоположение файла, а не с помощью потока, и она работает просто отлично, так что попробуйте чтобы посмотреть, как работают потоки, проблема может быть там. –

+0

Поцарапайте это, он даже работает с потоками. Что такое код за «Properties.Resources.greenTilePress'? –

+0

Properties.Resources.greenTilePress - это ресурс (.wav-файл). Я добавил проект визуальной студии, чтобы он был включен в exe. После вашего комментария я снова попробовал безпоточный подход, и он работал (я буквально скопировал и вставил код здесь). Я понятия не имею, почему это не сработало раньше. Спасибо за вашу помощь! –

ответ

1

Вы можете видеть в документации, что метод play() запускается в другом потоке, после этого вы можете сделать что-то еще, и он должен работать, поэтому ваша проблема с первым подходом отличается от того, что вы думаете.

Метод воспроизведения воспроизводит звук с использованием новой нити. Если вы вызываете Play , прежде чем файл WAV будет загружен в память, файл WAV будет загружен до начала воспроизведения. Вы можете использовать LoadAsync или Load метод для загрузки WAV-файла в память заранее. После того, как .wav-файл успешно загружен из потока или URL-адреса, в будущих вызовах воспроизведения методам SoundPlayer не потребуется перезагружать .wav-файл , пока не изменится путь к звуку. Если.wav-файл не был указан или он не загружается, метод воспроизведения будет воспроизводить звуковой сигнал по умолчанию .

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

+1

Я не вижу причины в коде, который вы опубликовали, насколько я понимаю, он должен работать, если у вас есть это на GIT, я могу клонировать его и проверять. –

+1

Да, первый код действительно работает. Я понятия не имею, почему это не сработало для меня раньше, но я, очевидно, что-то напортачил. Большое спасибо за ваше время и помощь! –