【发布时间】:2013-06-18 05:58:18
【问题描述】:
我正在创建一个索引器,它使需要处理的项目入队。索引器会将项目添加到其处理器。例如,它将添加 100 个项目,然后在 3 分钟内不添加项目并添加另外 50 个项目。
public class Processer
{
private ConcurrentQueue<Item> items;
public void AddItem(Item item)
{
this.items.Enqueue(item);
}
}
这些项目会随机进入,所以我将创建一个单独的线程来出列和处理这些项目。
最好的选择是什么?
-
不要使用集合,而是使用线程池:
public void AddItem(Item item) { ThreadPool.QueueUserWorkItem(function, item); }这将自动创建一个队列,并处理项目,但我控制较少,当找到 20 个项目时,它们几乎会停止我的索引器运行并首先完成这个线程池
-
使用长时间运行的任务:
public Processer() { this.task = Task.Factory.StartNew(() => DequeueItems(), CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default); } public DequeueItems() { while(true) { Item item = null; while(this.items.TryDequeue(out item) { this.store.ExecuteIndex((AbstractIndexCreationTask)item); } Thread.Sleep(100); } }但我讨厌必须使用的 while() 和 thread.sleep,因为可枚举的对象会在一段时间后干涸,并且需要重新检查是否有新项目。
-
使用短期运行任务:
public Processer() { } private void Run() { this.task = Task.Factory.StartNew(() => DequeueItems(), CancellationToken.None, TaskCreationOptions.PreferFairness, TaskScheduler.Default); } public void AddItem(Item item) { this.items.Add(item); if(this.task == null || this.task.isCompleted) this.Run(); } public DequeueItems() { Item item = null; while(this.items.TryDequeue(out item) { this.store.ExecuteIndex((AbstractIndexCreationTask)item); } }这可能会更好?但是启动一个线程是一个“昂贵”的操作,我不知道我是否会错过项目,因为我检查了 IsCompleted,这可能是在结束 while 循环的过程中,这样会丢失 1 个项目。但它不会休眠,并使用脏的 while 循环。
您的选择,由于 MSDN 建议使用 TPL,我认为不使用线程,但也许有更好的方法来处理这个问题
更新日志
- 更改为 BlockingCollection
- 改回并发队列
我检查过的一些事情:
- De-queue Items with worker threads(使用线程池)
- Thread queues for dummies(仅使用 Thread 解决方案,不使用 TPL)
- Unexpected behaviour for ThreadPool.QueueUserWorkItem(同上)
- C# - ThreadPool vs Tasks 声明使用多线程代码时首选 TPL
【问题讨论】:
-
是的,我知道我可以使用其他线程安全队列,但队列不是问题,我希望就处理此问题的最佳实践获得一些反馈。
-
@user2331234:不,队列非常是的问题。它不是线程安全的,而
BlockingCollection<T>专为像您这样的生产者/消费者情况而设计。 -
我的问题是如何添加一个单独的线程来处理项目。我将使用 BlockingCollection 调整上面的示例。但我仍然希望得到一些反馈,哪些选项用于使队列出队。
-
我发表评论后才看到您的编辑。我的理解是
GetConsumingEnumerable会无限期地等待直到CompleteAdding被调用,所以我还是不明白Thread.Sleep和while循环。
标签: c# multithreading task-parallel-library task threadpool