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 или поисками в стеке).
Я пытался воссоздать вашу проблему (первый, не нарезкой подход), но сделал это, указывая SoundPlayer на точное местоположение файла, а не с помощью потока, и она работает просто отлично, так что попробуйте чтобы посмотреть, как работают потоки, проблема может быть там. –
Поцарапайте это, он даже работает с потоками. Что такое код за «Properties.Resources.greenTilePress'? –
Properties.Resources.greenTilePress - это ресурс (.wav-файл). Я добавил проект визуальной студии, чтобы он был включен в exe. После вашего комментария я снова попробовал безпоточный подход, и он работал (я буквально скопировал и вставил код здесь). Я понятия не имею, почему это не сработало раньше. Спасибо за вашу помощь! –