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;
    }
}