C# 队列和线程
当队列需要可以在多个线程上访问C# 队列和线程,c#,multithreading,queue,C#,Multithreading,Queue,当队列需要可以在多个线程上访问Enqueue(),但只需要在单个主线程上访问Dequeue()时,在C中使用的最佳Queue数据结构是什么?我的线程结构如下所示: 主线程-用户 副生产商1 副生产商2 副秘书长3-生产商 我有一个队列,它保存子线程生成的所有项目,主线程调用Queue.Dequeue(),直到它为空。为此,我在主线程上调用了以下函数 public void ConsumeItems() { while (queue.Count > 0) {
Enqueue()
,但只需要在单个主线程上访问Dequeue()
时,在C中使用的最佳Queue
数据结构是什么?我的线程结构如下所示:
- 主线程-用户
- 副生产商1
- 副生产商2
- 副秘书长3-生产商
队列
,它保存子线程生成的所有项目,主线程调用Queue.Dequeue()
,直到它为空。为此,我在主线程上调用了以下函数
public void ConsumeItems()
{
while (queue.Count > 0)
{
var item = queue.Dequeue();
...
}
}
主线程在每个线程循环中调用此函数一次,我希望确保在线程安全的庄园中访问
队列
,但我也希望避免锁定队列
,如果可能的话,是出于性能原因。您希望使用的是默认情况下由a支持的。要从队列中取出项目,您可以从foreach内部使用.GetConsumingEnumerable()
public BlockingCollection<Item> queue = new BlockingCollection<Item>();
public void LoadItems()
{
var(var item in SomeDataSource())
{
queue.Add(item);
}
queue.CompleteAdding();
}
public void ConsumeItems()
{
foreach(var item in queue.GetConsumingEnumerable())
{
...
}
}
假设您希望从中获得一些信息。我将避免使用显式队列管理,而是查看TPL数据流库。一个生产者,许多消费者。解决方案不会改变,只是示例需要改变。
public Task ProcessDataAsync(IEnumerable<SomeInput> input)
{
using(var outfile = new File.OpenWrite("outfile.txt"))
{
//Create a convert action that uses the number of processors on the machine to create parallel blocks for processing.
var convertBlock = new TransformBlock<SomeInput, string>(x => CpuIntensiveConversion(x), new ExecutionDataflowBlockOptions {MaxDegreeOfParallelism = Enviorment.ProcessorCount});
//Create a single threaded action that writes out to the textwriter.
var writeBlock = new ActionBlock<string>(x => outfile.WriteLine(x))
//Link the convert block to the write block.
convertBlock.LinkTo(writeBlock, new DataflowLinkOptions{PropagateCompletion = true});
//Add items to the convert block's queue.
foreach(var item in input)
{
await convertBlock.SendAsync();
}
//Tell the convert block we are done adding. This will tell the write block it is done processing once all items are processed.
convertBlock.Complete();
//Wait for the write to finish writing out to the file;
await writeBlock.Completion;
}
}