程序在预警时,会发出报警音,当报警音频播放时间,超过预警频率时,就会像我们打印文档一样,像打印机发送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事件来实现连续播放

using System;
using System.Collections.Generic;
using NAudio.Wave; public class MyForm : Form
{
private Label myLabel; public MyForm()
{ } WaveOutEvent waveOut; 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();
} static void WaveOut_PlaybackStopped(object sender, StoppedEventArgs e)
{
//播放结束,要释放资源
if (waveOut != null && waveOut.PlaybackState == PlaybackState.Stopped)
{
waveOut.Dispose();
}
Console.WriteLine($"播放完成: {audioFiles[currentIndex - 1]}");
PlayNextAudio();
} static void PlayNextAudio()
{
if (currentIndex < audioFiles.Count)
{
var audioFile = new AudioFileReader(audioFiles[currentIndex]);
waveOut = new WaveOutEvent(); //播放完成释放,所以这边需要 重新创建 WaveOutEvent
waveOut.Init(audioFile);
waveOut.Play();
Console.WriteLine($"开始播放: {audioFiles[currentIndex]}");
currentIndex++;
}
else
{
Console.WriteLine("所有音频播放完成");
}
} private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
//窗体关系,要释放资源
if (waveOut != null)
{
waveOut.Stop();
waveOut.Dispose(); // 确保控件被释放
waveOut = null; // 防止重复释放和内存泄漏问题
}
}
}

关键点

显式释放资源:

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

重新创建 WaveOutEvent:

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

释放 AudioFileReader:

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

C# Winform 当音频播放完成后,播放下一个音频,怎么知道音频有没有播放完成的更多相关文章

  1. jquery层级原则器(匹配前一个元素后的下一个元素,必须是挨着的)

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. mpg123 - 播放 MPEG 1.0/2.0 Layer-1, -2, -3 音频文件

    语法 mpg123 [ -tscvqy01m24 ][ -b size ][ -k num ][ -n num ][ -f factor ][ -r rate ][ -g gain ][ -a dev ...

  3. JavaScript一个页面中有多个audio标签,其中一个播放结束后自动播放下一个,audio连续播放

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  4. 如何使用JW Player来播放Flash并隐藏控制按钮和自定义播放完成后执行的JS

    在一个客户项目中播放的flash需要进行定制如不显示控制按钮,flash播放完成后执行特定的js等,在用过了N多的JQery插件和播放器后最终JW Player插件可以满足我的以上要求 因为JW Pl ...

  5. video视频标签一些设置,包括封面、播放结束后的封面、视频占满屏幕的方式、视频播放暂停、展示控制栏、触发全屏播放事件

    video视频标签一些设置,包括封面.播放结束后的封面.视频占满屏幕的方式.视频链接.视频播放暂停.展示控制栏.触发全屏播放事件 <video id="video" auto ...

  6. video设置视频的播放位置(本例中实现效果是视频第一次播放完成后,接下来中从视频的中间部位开始循环播放)

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

  7. html5 播放多个视频。一个接一个的播放

    new个video,指定播放列表的第一个视频路径为src.监听end事件,回调里面把video的src改成列表的下一个,再play. 示意代码:var vList = ['视频地址url1', 'ur ...

  8. Swift - 制作一个录音机(声音的录制与播放)

    1,技术介绍 (1)AVFoundation.framework框架提供了AVAudioRecorder类.它可以实现录音功能. (2)而使用该框架的AVAudioPlayer类,可以实现声音的播放. ...

  9. 利用videojs自动播放下一个

    利用videojs自动播放下一个 一.总结 一句话总结: 在视频放完的ended方法里面,指定video的src,然后this.play()放视频就好 vue来控制视频的链接也是蛮不错的 this.o ...

  10. SNF快速开发平台MVC-审核流,审核完成后会给下一个审核人发邮件,下一个审核人可以不登录系统,在邮件里进行审核处理

    审核流设计和使用参考以下资料: 审核流设计 http://www.cnblogs.com/spring_wang/p/4874531.html 审核流实例 http://www.cnblogs.com ...

随机推荐

  1. 【3分钟学会】一招禁用表单中input输入框回车键自动触发提交事件!

    知其然知其所以然 在前端项目开发中,偶尔会有表单提交的问题: 用户输入表单后,不小心按了回车键,导致提前触发了提交事件? 问题概述 当表单中仅有一个input输入框时,按下回车键就会自动触发提交事件, ...

  2. 树莓派下,打包发布能在树莓派中运行的Qt5程序和其运行环境

    目标:把Qt程序部署到新的树莓派中. 平台:树莓派 工作:把Qt程序和运行环境分别打包 一.程序打包过程如下,仅供参考: 1.新建文件夹A,把程序拷贝到文件夹中. 2.使用ldd获取依赖关系,并复制到 ...

  3. Chats 开发指南

    Chats 开发指南 欢迎使用 Chats!在我上一篇博客 https://www.cnblogs.com/sdcb/p/18597030/sdcb-chats-intro 中,我介绍了 Chats ...

  4. MethodHandler 不会产生 boxing

    static int add(int a, int b){ return a + b; } @Test public void directAdd() throws Throwable { // 编译 ...

  5. 【Python自动化】selenium简单应用

    准备工作 查询浏览器版本 chrome://version/ 下载驱动 https://chromedriver.storage.googleapis.com/index.html 下载的驱动版本要和 ...

  6. 如何调整Gitlab-Runner最大并发数?

    概述: 我们在使用gitlab-runner做cicd时,如果安装之后没有配置gitlab-runner的最大并发数,在使用时候可能会碰到job的警告(job日志超过字节限制):job's log e ...

  7. k8s calico-node错误日志 listen tcp: lookup localhost on 8.8.4.4:53: no such host

    项目场景:K8s搭建 问题描述:查看pods状态,发现 calico-node异常[root@k8s-master ~]# kubectl get pods --all-namespacesNAMES ...

  8. Hutool excel导出

    easyExcel 文档不是很友好,所以转用hutool 工具导出excel,百度到的很多都没多少营养,略作总结,望君不吝赐教.该篇博客可以让你画出不是太复杂的excel 如:   image.png ...

  9. Mybatisplus实现MetaObjectHandler接口自动更新创建时间更新时间

    踩坑: 直接实现该接口,发现进入该类后的entity已经重新处理updateTime了,但是更新数据库的时候,却不带updateTime更新. 原因: 由于对该接口等认识不足导致. 解决方案: 实体类 ...

  10. opencv只在bin目录下编译dll,在lib目录下编译lib,在bin目录下不编译测试程序的各种exe

    penCV是一个开源的计算机视觉库,它提供了多种编程语言的接口.如果你只想编译出DLL和Lib库文件,而不编译EXE(可执行文件),这通常是因为你想要进行某种形式的动态链接或者库的分发,而不关心EXE ...