FIFO / QUEUE带有缓冲区和线程安全性

4

我收到了大量的统计数据,需要将其插入数据库中。 我想实现一种队列或FIFO类,以保留所有数据,并在达到特定计数(缓冲区)时通过批量插入将其发送到SQL。这应该是线程安全的。

我知道如何进行批量插入。 有什么建议可以制作队列/列表吗?

谢谢


你是否在运行 .Net 4? - svick
3个回答

2

.net基础类库中有ConcurrentQueue(Of T)。只需导入System.Collections.Concurrent

编辑: 如果必须使用队列,您可以创建一个包装器类/模块,在计数器(缓冲区)达到一定数量时触发事件。


当您达到缓冲区限制并将其作为线程安全的回调函数时,怎么样? - Shay

0

如果您不需要严格的FIFO,我认为您应该使用BlockingCollection

它是线程安全的,实现方式可能如下:

var collection = new BlockingCollection<Data>();

var sqlinserter = Task.Factory.StartNew(UpdateSql());

while (true) {
    Data statistics = FetchStatistics();
    if (statistics == null)
        break;
    collection.Add(statistics);
}
collection.CompleteAdding();
sqlinserter.Wait();

编辑 看到您想要在每个批次中插入特定数量的项目

void UpdateSql() {
    var batch = new List<Data>();
    foreach (var item in collection.GetConsumingEnumerable()) {
        batch.Add(item);
        if (batch.Count > SomeBatchSize) {
            InsertIntoSql(batch);
            batch.Clear();
        }
    }
    if (batch.Count > 0)
        InsertIntoSql(batch); // insert remaining items
}

-1

这是一种安全的处理方式。 主要是要避免任何可能导致你"被卡住"在同步锁内部的情况。

Public Class TSQueue(Of T)

    Private q As New Queue(Of T)
    Public Property threshold As Integer = 100
    Public Event ThresholdHit As EventHandler(Of EventArgs)

    Public Sub EnqueueSafe(value As T)
        Dim notify As Boolean = False
        SyncLock q
            q.Enqueue(value)
            If q.Count >= threshold Then
                notify = True
            End If
        End SyncLock
        If notify Then
            RaiseEvent ThresholdHit(Me, EventArgs.Empty)
        End If
    End Sub

    Public Function DequeueSafe() As T
        SyncLock q
            Return q.Dequeue()
        End SyncLock
    End Function

    Public Function DequeueAllSafe() As T()
        Dim out() As T
        SyncLock q
            out = q.ToArray()
            q.Clear()
        End SyncLock
        Return out
    End Function

    Public Function CountSafe() As Integer
        SyncLock q
            Return q.Count
        End SyncLock
    End Function

End Class

我很惊讶这不是答案,因为问题实际上是“...实现一些队列或FIFO类来保留所有数据,并在达到特定计数(缓冲区)时通过批量插入将其发送到SQL。这应该是线程安全的。有什么建议如何制作队列/列表?”事件ThresholdHit将触发数据转储,后台队列通过synclock语句是线程安全的。 - DarrenMB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接