.NET中的多线程任务队列实现

时间:2010-10-17 12:09:03

标签: .net multithreading

我很头疼 - 我的服务器应用程序在负载下超过了最大的开放数据库连接。所以,我想我需要一个任务队列(也就是服务总线)来进行写数据库访问。一个队列,db写请求可以发布到它,专用线程将读取并执行。

我想知道是否有准备好的组件可以做到这一点。我的要求是:

  1. 多个线程可以最小阻塞地写入队列。
  2. 多个线程可以从队列中读取以执行发布的写入请求。在最受约束的情况下,此数字为1,但可能更多,例如开放数据库连接限制的10%。
  3. 有什么想法吗?

    感谢。

    P.S。

    我注意到thisthis,但似乎与我无关。

3 个答案:

答案 0 :(得分:11)

使用实现生产者/消费者模式的BlockingCollection<T>。它是线程安全的,因此您可以同时从多个线程访问它。以下是如何使用它的示例:

var collection = new BlockingCollection<MyClass>();

// start a new background task to fill the queue
Task.Factory.StartNew(() => {
    while(thereIsStillStuffToStoreInTheDatabase)
    {
        var item = GetNextItem();
        collection.Add(item);
    }
    collection.CompleteAdding();
});

// GetConsumingEnumerable() blocks while empty until the producer
// has more items or it signals that adding is complete
foreach(var item in collection.GetConsumingEnumerable())
{
    // store item in database
}

请注意,上述实现也可以反向执行,后台Task消耗来自集合,主工作线程填充它。

约瑟夫·阿尔巴哈里(Joseph Albahari)对任务和并行性有很好的写作。您可以阅读所有相关信息,特别是关于BlockingCollection,here

答案 1 :(得分:2)

在.NET 4的过程中,您的出发点几乎肯定应该是:

  1. BlockingCollection<T>
  2. 使用并行LINQ方法,例如Parallel.Foreach传递ParallelOptions实例并设置MaxDegreeOfParallelism

答案 2 :(得分:0)

.net 4.0提供了几种线程安全的数据结构 ConcurrentQueue<T>应该是你想要的。

它缺少阻塞出队或事件表明某事已入队。因此,如果需要,您需要自己实现这样的信号。