c# - 我可以更好地优化这个并发吗?

标签 c# .net multithreading concurrency

我最近开始编写我的第一个多线程代码,非常感谢您提出一些意见。

它从缓冲区中传送视频样本,该缓冲区由流解析器在后台填充(超出此问题的范围)。如果缓冲区为空,则需要等到缓冲区级别变得可接受后再继续。

代码适用于 Silverlight 4,删除了一些错误检查:

// External class requests samples - can happen multiple times concurrently
protected override void GetSampleAsync()
{
    Interlocked.Add(ref getVideoSampleRequestsOutstanding, 1);                
}

// Runs on a background thread
void DoVideoPumping()
{
    do
    {
        if (getVideoSampleRequestsOutstanding > 0)
        {
            PumpNextVideoSample();

            // Decrement the counter
            Interlocked.Add(ref getVideoSampleRequestsOutstanding, -1);
        }
        else Thread.Sleep(0);  

    } while (!this.StopAllBackgroundThreads);
}       

void PumpNextVideoSample()
{
    // If the video sample buffer is empty, tell stream parser to give us more samples 
    bool MyVidBufferIsEmpty = false; bool hlsClientIsExhausted = false;
    ParseMoreSamplesIfMyVideoBufferIsLow(ref MyVidBufferIsEmpty, ref parserAtEndOfStream);

    if (parserAtEndOfStream)  // No more data, start running down buffers
        this.RunningDownVideoBuffer = true;
    else if (MyVidBufferIsEmpty)  
    {
        // Buffer is empty, wait for samples
        WaitingOnEmptyVideoBuffer = true;
        WaitOnEmptyVideoBuffer.WaitOne();
    }

    // Buffer is OK
    nextSample = DeQueueVideoSample(); // thread-safe, returns NULL if a problem

    // Send the sample to the external renderer
    ReportGetSampleCompleted(nextSample);

}

代码似乎运行良好。但是,有人告诉我使用 Thread.Wait(...) 是“邪恶的”:当没有请求样本时,我的代码会不必要地循环,占用 CPU 时间。

我的代码可以进一步优化吗?由于我的类(class)是为需要样本的环境设计的,潜在的“无意义循环”场景是否超过了其当前设计的简单性?

非常感谢评论。

最佳答案

这看起来像经典的生产者/消费者模式。解决此问题的常规方法是使用所谓的阻塞队列。

.net 4.0 版引入了一套高效、精心设计的 concurrent collection classes对于这种类型的问题。我想 BlockingCollection<T> 将满足您当前的需求。

如果您无法访问 .net 4.0,那么有很多网站都包含阻塞队列的实现。我个人的标准引用是 Joe Duffy 的书,Concurrent Programming on Windows .一个好的开始是 Marc Gravell's blocking queue presented here in Stack Overflow .

使用阻塞队列的第一个好处是你可以停止使用繁忙的等待循环,停止对 Sleep() 的 hacky 调用。等等。使用阻塞队列来避免这种代码总是一个好主意。

但是,我发现使用阻塞队列有一个更重要的好处。目前,您用于生成工作项、使用它们和处理队列的代码都是混合在一起的。如果您正确使用阻塞队列,那么您最终会得到更好的分解代码,这些代码将算法的各个组件分开:队列、生产者和消费者。

关于c# - 我可以更好地优化这个并发吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5868794/

相关文章:

c# - 我应该为我使用的每个数据库设置一个类吗?

c# - .NET 软件更新管理器

c# - 在非托管回调委托(delegate)中抛出异常的含义

python - 如何在多核多线程上运行 TensorFlow

c# - 如何使用中间 API 传递 JSON 对象?

c# - 静态字符串与非静态字符串

c# - 如何启动Azure Function

c# - 合并两个列表并从列表 A 中减去列表 B 的值

c - 使用一个信号量实现两个线程的线程同步

pthreads 程序的竞争条件会使操作系统或 X 完全崩溃吗?