安全清除列表(并发)
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
是合适的。您也可以实现自己的并发集合,尽管这要复杂得多。
美好的一天!
我有 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
是合适的。您也可以实现自己的并发集合,尽管这要复杂得多。