C# 流媒体播放音乐时CPU贪婪循环

C# 流媒体播放音乐时CPU贪婪循环,c#,performance,audio-streaming,C#,Performance,Audio Streaming,为了提供一些背景信息,我正在开发一个开源的替代桌面Spotify客户端,其核心是可访问性。你还会在这里看到一些恶心的东西 我注意到播放一开始CPU的使用就非常紧张。即使暂停,CPU也很高 我运行了VisualStudio的内置剖析器,试图揭示可能正在发生的任何资源消耗。正如我所怀疑的,问题出在我的播放管理器的流循环中 探查器标记为最富示例的代码如下: const int secondsToBuffer = 3; private void GetStreaming(object stat

为了提供一些背景信息,我正在开发一个开源的替代桌面Spotify客户端,其核心是可访问性。你还会在这里看到一些恶心的东西

我注意到播放一开始CPU的使用就非常紧张。即使暂停,CPU也很高


我运行了VisualStudio的内置剖析器,试图揭示可能正在发生的任何资源消耗。正如我所怀疑的,问题出在我的播放管理器的流循环中

探查器标记为最富示例的代码如下:

const int secondsToBuffer = 3;

    private void GetStreaming(object state)
    {
        this.fullyDownloaded = false;
        // secondsToBuffer is an integer to represent how many seconds we should buffer up at once to prevent choppy playback on slow connections

        try
        {
            do
            {
                if (bufferedWaveProvider == null)
                {
                    this.bufferedWaveProvider = new BufferedWaveProvider(new WaveFormat(44100, 2));
                    this.bufferedWaveProvider.BufferDuration = TimeSpan.FromSeconds(20); // allow us to get well ahead of ourselves
                    Logger.WriteDebug("Creating buffered wave provider");
                    this.gatekeeper.MinimumSampleSize = bufferedWaveProvider.WaveFormat.AverageBytesPerSecond * secondsToBuffer;
                }
                // this bit in particular seems to be the hot point
                if (bufferedWaveProvider != null && bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes < bufferedWaveProvider.WaveFormat.AverageBytesPerSecond / 4)
                {
                    Logger.WriteDebug("Buffer getting full, taking a break");
                    Thread.Sleep(500);
                }
                // do we have at least double the buffered sample's size in free space, just in case
                else if (bufferedWaveProvider.BufferLength - bufferedWaveProvider.BufferedBytes > bufferedWaveProvider.WaveFormat.AverageBytesPerSecond * (secondsToBuffer * 2))
                {
                    var sample = gatekeeper.Read();
                    if (sample != null)
                    {
                        bufferedWaveProvider.AddSamples(sample, 0, sample.Length);
                    }
                }
            } while (playbackState != StreamingPlaybackState.Stopped);
            Logger.WriteDebug("Playback stopped");
        }
        finally
        {
            // no post-processing work here, right?
        }
    }
const int secondsToBuffer=3;
私有流(对象状态)
{
this.fullydownload=false;
//secondsToBuffer是一个整数,表示我们应该一次缓冲多少秒,以防止在慢速连接上出现断断续续的播放
尝试
{
做
{
if(bufferedWaveProvider==null)
{
this.bufferedWaveProvider=新的bufferedWaveProvider(新的波形格式(44100,2));
this.bufferedWaveProvider.BufferDuration=TimeSpan.FromSeconds(20);//让我们走在前面
WriteDebug(“创建缓冲波提供程序”);
this.gatekeeper.MinimumSampleSize=bufferedWaveProvider.WaveFormat.AverageBytesPerSecond*secondsToBuffer;
}
//特别是这一点似乎是热点
if(bufferedWaveProvider!=null&&bufferedWaveProvider.BufferLength-bufferedWaveProvider.BufferedBytesbufferedWaveProvider.WaveFormat.AverageBytesPerSecond*(secondsToBuffer*2))
{
var sample=gatekeeper.Read();
if(示例!=null)
{
bufferedWaveProvider.AddSamples(sample,0,sample.Length);
}
}
}while(playbackState!=StreamingPlaybackState.Stopped);
Logger.WriteDebug(“播放停止”);
}
最后
{
//这里没有后期处理工作,对吗?
}
}
NAudio样本是我用这种方法处理流媒体的灵感来源。要查找完整文件的源代码,可以在此处查看:

我是一个分析方面的新手,而且我也不是流媒体方面的年度专家(这两个方面可能都很明显)

有没有什么方法可以让这个循环减少资源密集型。在缓冲区已满的if块中增加睡眠量会有帮助吗?还是我找错树了。看起来会的,但我想半秒钟就足够了


感谢您的帮助

基本上,您已经创建了一个无限循环,直到缓冲区满为止。您标记的部分

// this bit in particular seems to be the hot point
很可能是因为if语句中的计算只是一次又一次地重复;是否可以将其中任何一个移动到循环之外


我会在while语句之前放一个Thread.Sleep(50),以防止颠簸,并看看这是否会产生影响(我怀疑会有影响)。

使用探查器并运行探查器。VisualStudio有一个。学习使用它。“我运行Visual Studio内置的探查器,试图了解可能正在发生的任何资源占用。”我无法将计算移出循环,因为它们需要反映缓冲区当时的状态。不过,一次睡眠带来了巨大的变化。非常感谢。在循环结束时,我给了它250毫秒的睡眠时间,在与VS(在我通过上下文菜单自行构建之前,VS没有使用最新版本的回放程序集)进行一些修改后,CPU使用率大幅下降