首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何在C#控制台应用程序中正确实现声音?

如何在C#控制台应用程序中正确实现声音?
EN

Stack Overflow用户
提问于 2018-01-17 14:38:17
回答 1查看 2.4K关注 0票数 3

我已经创建了一个控制台应用程序,它可以在控制台屏幕的任何地方创建文本。我想要创建一个类似效果的打字机,所以我从打字机中导入了一个击键声音,并在我的项目中使用了它。在屏幕上输入字符时,很难同步播放声音,所以我创建了一个名为声音的类,它为我想要在后台运行的每个声音创建一个背景线程。

现在我的字符与打字机的声音同步,我添加了一个新的声音文件。无论何时有新行,该文件都应播放。我现在面临的问题是,新的打字机车厢回音正在播放,突然停了下来。为了解决这个问题,我在PlaySync实例中添加了SoundPlayer ()命令。这允许我在后台播放新文件,但是当执行下一条消息时,回车声音仍然在播放,而字符正在被键入到控制台。回车结束后,击键声恢复正常。

我知道了发生这种情况的原因: PlaySync()将确保声音被加载和播放,然后恢复正常的操作。如果我使用的是PlaySync以外的任何东西,那么返回的车次将很快,甚至会被听到。我试过拖延一下,但还是不够完美。我想能够听到敲击的声音正在播放,一旦字符被键入。当执行新行时,我希望能够听到回车的声音。所有进程都必须在这个回车声音完成循环之后等待。同步这些声音的正确方法是什么?我的逻辑有缺陷吗?

Screen.cs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CanizHospital
{
    public class Screen
    {
        private Sounds sounds;
        private const int delay = 300;
        private static int _leftPos;
        private static int _topPos;

        public Screen(int leftPos, int topPos, int screenWidth, int screenHeight)
        {
            _leftPos = leftPos;
            _topPos = topPos;
            sounds = new Sounds();
            SetUpScreen(screenWidth, screenHeight);
        }

        private static void SetUpScreen(int width, int height)
        {
            IntPtr ptr = GetConsoleWindow();
            MoveWindow(ptr, 0, 0, 1000, 400, true);
            Console.SetWindowSize(width, height);
        }

        public void WriteAt(string message, int x, int y, bool typeWritter)
        {
            try
            {
                Console.SetCursorPosition(_leftPos + x, _topPos + y);
                if(typeWritter && message != null)
                {
                    TypeWritter(message, delay);
                }
            }
            catch(ArgumentOutOfRangeException e)
            {
                Console.Clear();
                Console.Beep(37, 500);
                Console.Write(e.Message);
            }
        }

        public void TypeWritter(string message, int delay, bool newLine = true)
        {

            foreach (char c in message)
            {

                Console.Write(c);
                sounds.LoadTypewriterSound();
                Thread.Sleep(delay);
            }


            if(newLine)
            {    
                Console.Write(Environment.NewLine);
                sounds.LoadCarriageReturn();
                Thread.Sleep(delay);
            }    
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr GetConsoleWindow();

        [DllImport("user32.dll", SetLastError = true)]
        internal static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint);
    }
}

Sounds.cs

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Media;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace CanizHospital
{
    class Sounds
    {

        public void LoadTypewriterSound()
        {
            Thread backgroundSound = new Thread(new ThreadStart(PlayKey));
            backgroundSound.IsBackground = true;
            backgroundSound.Start();
        }

        public void LoadCarriageReturn()
        {
            Thread backgroundSound = new Thread(new ThreadStart(PlayCarriageReturn));
            backgroundSound.IsBackground = true;
            backgroundSound.Start();
        }

        private static void PlayKey()
        {
            SoundPlayer player = new SoundPlayer();
            player.SoundLocation = @"C:\Users\Erick\Desktop\C#\CanizHospital\CanizHospital\typewriter-key-1.wav";
            player.Play();
        }

        private static void PlayCarriageReturn()
        {
            SoundPlayer player = new SoundPlayer();
            player.SoundLocation = @"C:\Users\Erick\Desktop\C#\CanizHospital\CanizHospital\typewriter-return-1.wav";
            player.PlaySync();
        }
    }
}

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Threading;
using Console = Colorful.Console;
using Colorful;

namespace CanizHospital
{
    class Program
    {

        static void Main(string[] args)
        {
            Screen screen = new Screen(Console.CursorLeft, Console.CursorTop, 
                Console.LargestWindowWidth, Console.LargestWindowHeight);


            screen.WriteAt("Hi whats up", 0, 0, true);
            //Thread.sleep(500);  //Delay here wont stop process
            screen.WriteAt("Hi whats up", 1, 1, true);
        }
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-17 16:10:18

首先,您不需要创建一个新线程来保存一个SoundPlayer实例来调用Play()。您可以在Play()之前调用Console.Write,在延迟之后调用Stop() (或者您无法听到任何消息,因为它停止得太快)。从MSDN,Play()方法

使用.wav新线程播放文件,如果未加载.wav文件,则先加载.wav文件。

其次,PlaySync()在完成之前阻止执行,这完全符合您的要求:

PlaySync方法使用当前线程来播放.wav文件,防止线程在加载完成之前处理其他消息。

下面是按照所需方式工作的代码片段:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public void TypeWritter(string message, int delay, bool newLine = true)
{
    var player = new SoundPlayer
    {
        SoundLocation = @"C:\Users\Erick\Desktop\C#\CanizHospital\CanizHospital\typewriter-key-1.wav"
    };
    foreach (char c in message)
    {
        player.Play();
        Console.Write(c);
        Thread.Sleep(delay);
        player.Stop();
    }
    if (newLine)
    {
        Console.Write(Environment.NewLine);
        player.SoundLocation = @"C:\Users\Erick\Desktop\C#\CanizHospital\CanizHospital\typewriter-return-1.wav";
        player.PlaySync();
        //Thread.Sleep(delay); // Might not be necessary
    }
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48311157

复制
相关文章
用C#实现模拟双色球中奖控制台应用程序
简单地运用CSharp语言和.net平台,如变量、方法、类、数组、字典、系统函数、规范的注释、控制台输出、文件的读写、程序怎样设计等。
摘繁华
2022/08/31
1.2K0
用C#实现模拟双色球中奖控制台应用程序
用C#实现模拟双色球中奖控制台应用程序
简单地运用CSharp语言和.net平台,如变量、方法、类、数组、字典、系统函数、规范的注释、控制台输出、文件的读写、程序怎样设计等。
摘繁华
2022/05/03
1.4K0
用C#实现模拟双色球中奖控制台应用程序
C# 控制台应用程序输出颜色字体[更正版]
首先感谢院子里的“yanxinchen”,之前的方法是通过c#调用系统api实现的,相比之下我的有点画蛇添足了,哈哈。 最佳解决方案的代码: static void Main(string[] args) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Hello, color text!"); Console.ForegroundColor = ConsoleColor.Red; Cons
磊哥
2018/05/09
2K0
C# 控制台应用程序输出颜色字体[更正版]
使用C#创建SQLite控制台应用程序
本文介绍了如何使用C#和SQLite数据库来创建一个简单的登录系统,并给出了具体的代码示例。主要实现了用户登录、注册、修改个人信息和查询个人信息等功能。使用了SQLiteStudio工具来创建数据库,并使用了System.Data.SQLite.dll库进行数据库操作。
CNXY
2017/12/25
2.5K0
使用C#创建SQLite控制台应用程序
使用C#创建WCF服务控制台应用程序
本文介绍如何使用C#创建WCF服务控制台应用程序。首先,作者演示了如何将WCF服务添加到现有的Visual Studio 2019项目。然后,他演示了如何编写服务合同,并添加数据契约。最后,他演示了如何将控制台应用程序与WCF服务连接,并调用服务的方法。
CNXY
2017/12/25
2.1K0
使用C#创建WCF服务控制台应用程序
CSharp实现模拟双色球控制台应用程序
这是我在大一第一学期C#的课程设计,要求编写一个模拟双色球彩票的控制台应用程序,用以实现简单的模拟选购彩票。
摘繁华
2021/12/27
1.6K0
CSharp实现模拟双色球控制台应用程序
「业务架构」如何在BPMN中正确使用泳道
池是设置业务流程边界的基本BPMN元素。池最多包含一个业务流程。这意味着两个流程程必须在两个不同的池中建模。池可以以将要执行的流程的形式具有可见的内部详细信息(称为“白盒池”),或者池可能没有可见的内部详细信息(称为“黑盒池”)。应该使用的池类型取决于所需的详细程度和特定的上下文。
架构师研究会
2020/07/20
2.2K0
「业务架构」如何在BPMN中正确使用泳道
[C#]实现任何数据库类型的DbHelper帮助类 使用C#创建SQLite控制台应用程序
我们可以看到,在此类中,有很多用于创建数据库相关对象的类型,如DbConnection,DbCommand,DbDataAdapter等。
CNXY
2019/05/24
4.2K0
聊聊如何在spring事务中正确进行远程调用
最近和朋友聊天,他说他承接的外包项目遇到了分布式事务问题,问我有没啥解决方案,我本可以直接跟他说,分布式事务方案网上一大堆,什么tcc、可靠消息一致性、最大努力通知之类的,直接网上找个试下,比如直接用阿里的seata。但我并没有这么做,因为分布式事务,本来就是一个很复杂的课题,真正落地的时候,会发现有时候是多种分布式方案一起混用,而非一种方案走到黑。
lyb-geek
2022/01/07
7110
如何在Laravel 5中正确设置文件权限
为任何Web应用程序设置适当的文件权限是Web托管的重要部分。 在本教程中,您将学习如何在Linux Web服务器上托管的Laravel应用程序上正确配置文件权限。
星哥玩云
2022/07/27
5.7K0
如何在Pytorch中正确设计并加载数据集
但在实际的训练过程中,如何正确编写、使用加载数据集的代码同样是不可缺少的一环,在不同的任务中不同数据格式的任务中,加载数据的代码难免会有差别。为了避免重复编写并且避免一些与算法无关的错误,我们有必要讨论一下如何正确加载数据集。
老潘
2023/10/19
3990
如何在Pytorch中正确设计并加载数据集
聊聊如何在spring事务中正确进行远程调用
最近和朋友聊天,他说他承接的外包项目遇到了分布式事务问题,问我有没啥解决方案,我本可以直接跟他说,分布式事务方案网上一大堆,什么tcc、可靠消息一致性、最大努力通知之类的,直接网上找个试下,比如直接用阿里的seata。但我并没有这么做,因为分布式事务,本来就是一个很复杂的课题,真正落地的时候,会发现有时候是多种分布式方案一起混用,而非一种方案走到黑。
lyb-geek
2021/04/29
1K0
聊聊如何在spring事务中正确进行远程调用
[C#] 控制台应用程序退出事件
在 .NET 中,是否有一种方法(例如事件)来检测控制台应用程序何时退出?你可能需要清理一些线程和 COM 对象.,记录一下信息等等。。。。。。。 比如我的数据采集软件,每次启动和退出时向钉钉推送相关
科控物联
2022/04/19
2.9K0
[C#] 控制台应用程序退出事件
如何在 Node.js 中正确的使用日志对象
日志,是开发者排查问题的非常重要的手段,有时候甚至是唯一的,所以如何合理并正确的打印日志,成了开发时的重中之重。
程序狗
2022/01/04
1.1K0
如何在 JS 循环中正确使用 async 与 await
你想从fruitBasket获得每个水果的数量。 要获取水果的数量,可以使用getNumFruit函数。
前端小智@大迁世界
2019/06/15
5K0
如何在网页设计中正确应用色彩?
以下内容由摹客团队翻译整理,仅供学习交流,摹客iDoc是支持智能标注和切图的产品协作设计神器。
奔跑的小鹿
2019/06/24
1.2K0
如何在 JS 循环中正确使用 async 与 await
async 与 await 的使用方式相对简单。 当你尝试在循环中使用await时,事情就会变得复杂一些。
桃翁
2019/06/18
4.6K0
如何在 JS 循环中正确使用 async 与 await
如何在 Node.js 中正确的使用日志对象
地址:https://mp.weixin.qq.com/s/Pb51aYdrxAALM_wR4asDgg
coder_koala
2021/08/26
9840
C# 控制台使用 UAC 权限
本文告诉大家如何在 C# 控制台项目使用 UAC 权限。这个方法在 WPF 和 控制台都是可以使用。
林德熙
2018/09/19
1.5K0
C# 控制台使用 UAC 权限
如何在 Linux 上锁定虚拟控制台会话 如何在 Linux 上锁定虚拟控制台会话
当你在共享的系统上工作时,你可能不希望其他用户偷窥你的控制台中看你在做什么。如果是这样,我知道有个简单的技巧来锁定自己的会话,同时仍然允许其他用户在其他虚拟控制台上使用该系统。要感谢 Vlock(Virtual Console lock),这是一个命令行程序,用于锁定 Linux 控制台上的一个或多个会话。如有必要,你可以锁定整个控制台并完全禁用虚拟控制台切换功能。Vlock 对于有多个用户访问控制台的共享 Linux 系统特别有用。
用户8639654
2021/10/26
2.2K0

相似问题

如何在libgdx中正确地实现声音切换?

14

我如何实现声音通知,如whatsapp?

13

如何在C#中正确退出/停止/处置控制台应用程序

31

如何在c#控制台应用程序中正确处理异常

11

如何在C#控制台应用程序中正确写出下载状态?

42
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文