安全清除列表(并发)

Safely clear List (with concurrency)

美好的一天! 我有 List<byte> soundBuffer - 从麦克风获取音频信号。

void _waveInStream_DataAvailable(object sender, WaveInEventArgs e)
{
  lock(_lockObject)
   {
    for (int i = 0; i < e.BytesRecorded; i++)
            {
                _soundBuffer.Add(e.Buffer[i]);
            }
   }
}

如果用户等待很长时间,类型缓冲区将非常大(每分钟 2 MB)。 所以,我创建了一个计时器:

 _timerSoundCount = new System.Timers.Timer();
 _timerSoundCount.Interval = 10000;  // check every 10 second
 _timerSoundCount.Enabled = true;
 _timerSoundCount.Elapsed += _timerSoundCount_Elapsed;
 _timerSoundCount.Start();

并且:

void _timerSoundCount_Elapsed(object sender, ElapsedEventArgs e)
    {
        if(_soundBuffer.Count>2*1024*1024)
       {
        var energy = GetSignalEnergy(_soundBuffer);
        if(energy<1) //if energy of signal is small- clear buffer.
        {
            lock (_lockObject)
                _soundBuffer.Clear();
        }
        }
        else if(_soundBuffer.Count>=5*1024*1024)
         {... the same operation}
        else if(_sounfBuffer.Count>=10*1024*1024)
         { _soundBuffer.Clear();//very big buffer }
    }

我每 10 秒检查一次缓冲区大小。如果它太大-我只是清除缓冲区,因为我可以检测到 Speech\Silence 并在该代码处清除缓冲区。

所以,要点是:当我在计时器上执行 _soundBuffer.Clear() 并同时在 _waveInStream_DataAvailable 时,我会向缓冲区添加新字节吗? 会不会是死锁?

如果是这样,你能帮我如何安全地清除缓冲区吗?

谢谢!

如果这两个操作是从同一个线程执行的,则不会发生死锁。

如果同时有多个线程writing/reading列表,那么应该用lock(https://msdn.microsoft.com/en-us/library/c5kehkcz.aspx) to prevent multiple threads accessing the object simultaneously. See here (use the same lock object at two different code block?)来举个简单的例子

或者,您可以使用来自 System.Collections.Concurrent 命名空间 (https://msdn.microsoft.com/en-us/library/system.collections.concurrent(v=vs.110).aspx) 的并发集合。如果数据不是随机访问的,也许 ConcurrentQueue 是合适的。您也可以实现自己的并发集合,尽管这要复杂得多。