[英]Creating a buffer for Consumer and Producer threads using Queue c# .NET
我正在编写一个Windows服务应用程序,该应用程序能够从温度,压力量等传感器收集数据。
读取数据的频率非常高,可能有一百个传感器,并且接收到的数据的频率可能是每个传感器每秒一个。
我需要将这些数据存储到oracle数据库中,出于明显的原因,我不想以如此高的速度命中数据库。
因此,我想创建一个缓冲区。
我的计划是使用标准的.NET Queue创建一个Buffer,一些线程将Enqueue数据保留到队列中,而另一个由计时器驱动的线程可以按固定的时间间隔继续写入数据库。
我想知道的是.. ?? 这个线程安全吗?如果不是,那么创建内存缓冲区的最佳方法是什么?
为了回答您的问题,只要您锁定访问,就可以让多个线程访问常规队列。
但是对我而言,我没有使用它,而是想使用带有锁的队列来确保它们的线程安全。 我一直在用C#编写我的程序之一。 我只使用一个常规队列,然后在对它的访问中放入一个存储柜(入队,出队,计数)。 如果您仅锁定访问权限,则完全是线程安全的。
我的设置来自此处的教程/示例: http : //www.albahari.com/threading/part2.aspx#_ProducerConsumerQWaitHandle
我的情况与您的情况略有不同,但非常相似。 对我来说,我的数据可以非常快地输入,如果我不排队,那么如果同时输入多个数据,我会丢失数据。 然后,我运行了一个线程,该线程慢慢将项目从队列中移出并进行处理。 此交接使用AutoResetEvent来保存我的工作线程,直到准备好处理数据为止。 在您的情况下,您将使用计时器或定期发生的事情。
我复制/粘贴了我的代码,并试图更改名称。 希望我不会因为缺少一些名称更改而完全打破它,但是您应该能够掌握要点。
public class MyClass : IDisposable
{
private Thread sensorProcessingThread = null;
private Queue<SensorData> sensorQueue = new Queue<SensorData>();
private readonly object _sensorQueueLocker = new object();
private EventWaitHandle _whSensorEvent = new AutoResetEvent(false);
public MyClass () {
sensorProcessingThread = new Thread(sensorProcessingThread_DoWork);
sensorProcessingThread.Start();
}
public void Dispose()
{
// Signal the end by sending 'null'
EnqueueSensorEvent(null);
sensorProcessingThread.Join();
_whSensorEvent.Close();
}
// The fast sensor data comes in, locks queue, and then
// enqueues the data, and releases the EventWaitHandle
private void EnqueueSensorEvent( SensorData wd )
{
lock ( _sensorQueueLocker )
{
sensorQueue.Enqueue(wd);
_whSensorEvent.Set();
}
}
// When asynchronous events come in, I just throw them into queue
private void OnSensorEvent( object sender, MySensorArgs e )
{
EnqueueSensorEvent(new SensorData(sender, e));
}
// I have several types of events that can come in,
// they just get packaged up into the same "SensorData"
// struct, and I worry about the contents later
private void FileSystem_Changed( object sender, System.IO.FileSystemEventArgs e )
{
EnqueueSensorEvent(new SensorData(sender, e));
}
// This is the slower process that waits for new SensorData,
// and processes it. Note, if it sees 'null' as data,
// then it knows it should quit the while(true) loop.
private void sensorProcessingThread_DoWork( object obj )
{
while ( true )
{
SensorData wd = null;
lock ( _sensorQueueLocker )
{
if ( sensorQueue.Count > 0 )
{
wd = sensorQueue.Dequeue();
if ( wd == null )
{
// Quit the loop, thread finishes
return;
}
}
}
if ( wd != null )
{
try
{
// Call specific handlers for the type of SensorData that was received
if ( wd.isSensorDataType1 )
{
SensorDataType1_handler(wd.sender, wd.SensorDataType1Content);
}
else
{
FileSystemChanged_handler(wd.sender, wd.FileSystemChangedContent);
}
}
catch ( Exception exc )
{
// My sensor processing also has a chance of failing to process completely, so I have a retry
// methodology that gives up after 5 attempts
if ( wd.NumFailedUpdateAttempts < 5 )
{
wd.NumFailedUpdateAttempts++;
lock ( _sensorQueueLocker )
{
sensorQueue.Enqueue(wd);
}
}
else
{
log.Fatal("Can no longer try processing data", exc);
}
}
}
else
_whWatchEvent.WaitOne(); // No more tasks, wait for a signal
}
}
您可能会看到的是Microsoft的.net的Reactive(Rx)。 检出: https : //msdn.microsoft.com/zh-cn/data/gg577611.aspx ,页面底部是pdf教程“治愈异步布鲁斯”: http : //go.microsoft.com/fwlink /?LinkId = 208528这是非常不同的东西,但是也许您会看到自己喜欢的东西。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.