C# Winform 当音频播放完成后,播放下一个音频,怎么知道音频有没有播放完成

程序在预警时,会发出报警音,当报警音频播放时间,超过预警频率时,就会像我们打印文档一样,像打印机发送10次打印任务。当打出第1张纸的时候,这时候想取消打印。就不能在电脑端通过软件操作了。因此为了避免这种事情发生,就只有等打印机打完一张,再发下一个任务。这样的话,可以随时发起取消打印任务。

如果实现在报警音频结束前,不再给任务

SoundPlayer

在C#中,SoundPlayer 类本身没有直接提供事件或属性来检测音频是否播放完成。不过,你可以通过以下方法来实现这一功能:PlaySync 方法会阻塞当前线程,直到音频播放完成。你可以将播放操作放在一个单独的线程中,以避免阻塞主线程。
满足不了我想要的功能

using System; using System.Media; using System.Threading;  class Program {     static void Main()     {         string[] audioFiles = { "audio1.wav", "audio2.wav", "audio3.wav" };         SoundPlayer player = new SoundPlayer();          foreach (string file in audioFiles)         {             //TODO 如果任务取消,break 跳出循环             player.SoundLocation = file;             player.Load(); // 加载音频文件             player.PlaySync(); // 阻塞播放,直到当前音频播放完成             Console.WriteLine($"播放完成: {file}");         }          Console.WriteLine("所有音频播放完成");     } } 

优点:

  • 实现简单,代码直观。
  • 不需要额外的事件处理。

缺点:

  • PlaySync会阻塞当前线程,可能导致UI线程卡住(如果是在UI线程中运行)。

NAudio

C# Winform 通过 NAudio 获取控制电脑操作系统音量
NAudio库提供了更强大的音频处理功能,可以通过PlaybackStopped事件来实现连续播放
NAudio 中,WaveOutEvent 是一个用于播放音频的类,它封装了底层的音频设备资源。如果在使用完毕后没有调用 Dispose() 方法,垃圾回收器(GC)会在对象被回收时调用其析构函数(Finalize),但此时可能已经无法正确释放资源,从而导致错误。
如果 WaveOutEvent 使用了 AudioFileReader 或其他资源,确保这些资源也被释放:

using System; using System.Collections.Generic; using NAudio.Wave;  public class MyForm : Form {     private Label myLabel;      public MyForm()     {        }          WaveOutEvent waveOut;      AudioFileReader audioFile; //要单独拿出来,进行释放 	     List<string> audioFiles = new List<string> { "audio1.wav", "audio2.wav", "audio3.wav" };          private void OnLineCustodyOrderFrm_Load(object sender, EventArgs e)     {         waveOut = new WaveOutEvent();         waveOut.PlaybackStopped += WaveOut_PlaybackStopped;         PlayNextAudio();     }      private void WaveOut_PlaybackStopped(object sender, StoppedEventArgs e)     {         if (waveOut != null && waveOut.PlaybackState == PlaybackState.Stopped)         {             waveOut.Dispose();         }         Console.WriteLine($"播放完成: {audioFiles[currentIndex - 1]}");         PlayNextAudio();     }      private void PlayNextAudio()     {         if (currentIndex < audioFiles.Count)         {             audioFile = new AudioFileReader(audioFiles[currentIndex]);             waveOut.Init(audioFile);             waveOut.Play();             Console.WriteLine($"开始播放: {audioFiles[currentIndex]}");             currentIndex++;         }         else         {             Console.WriteLine("所有音频播放完成");         }     }      private void MyForm_FormClosing(object sender, FormClosingEventArgs e)     {          CloseWaveOut();     }      private void CloseWaveOut()     {         if (waveOut != null)         {            waveOut.Stop();         }         if (AudioFile != null)         {             AudioFile.Dispose();             AudioFile = null;         }         //窗体关系,要释放资源         if (waveOut != null)         {             waveOut.Dispose(); // 确保控件被释放             waveOut = null;         }     } } 

关键点
显式释放资源:

  • 在每次音频播放完成后,调用 waveOut.Dispose() 释放当前的 WaveOutEvent 对象。
  • 在程序退出前,确保释放所有资源。

重新创建 WaveOutEvent:

  • 每次播放新的音频文件时,重新创建一个新的 WaveOutEvent 对象,而不是复用之前的对象。

释放 AudioFileReader:

  • 如果使用了 AudioFileReader,也需要确保在播放完成后释放它。
发表评论

评论已关闭。

相关文章