生产者消费者中一旦有了数据,如何使消费者立即开始使用?

时间:2019-07-17 12:16:41

标签: c# design-patterns producer-consumer

我正在使用以下代码在C#中实现非常基本的生产者/消费者模式实现:

public class Engine
{
    private readonly BlockingCollection<string> _ProcessBuffer;
    private readonly BlockingCollection<string> _ProcessOutcome;

    public Engine()
    {
         _ProcessBuffer = new BlockingCollection<string>();
         _ProcessOutcome = new BlockingCollection<string>();
    }

    public void DoIt()
    {


        Task consumer = Task.Factory.StartNew(() =>
                                              {
                                                  Parallel.ForEach(_ProcessBuffer.GetConsumingEnumerable(), item => FooBar(item));
                                                  Console.WriteLine($"{DateTime.Now:mm:ss.fff}  Consume - CompleteAdding");
                                                  _ProcessOutcome.CompleteAdding();
                                                  Console.WriteLine($"{DateTime.Now:mm:ss.fff}  Consume - /CompleteAdding");
                                              }
        );

        Task producer = Task.Factory.StartNew(() =>
                                              {
                                                  //Use concurrent Q to enable safe enquing from multiple threads
                                                  //var exceptions = new ConcurrentQueue<Exception>();

                                                  //Some loop
                                                  for (int i = 0; i < 10; i++)
                                                  {
                                                      //Add something to the bag
                                                      Console.WriteLine($"{DateTime.Now:mm:ss.fff}  Produce - {i}");
                                                      _ProcessBuffer.Add(Convert.ToString(i));
                                                      Console.WriteLine($"{DateTime.Now:mm:ss.fff}  /Produce - {i}");
                                                  }

                                                  //Show we are all done
                                                  Console.WriteLine($"{DateTime.Now:mm:ss.fff}  Produce - CompleteAdding");
                                                  _ProcessBuffer.CompleteAdding();
                                                  Console.WriteLine($"{DateTime.Now:mm:ss.fff}  Produce - /CompleteAdding");
                                              }
        );

        consumer.Wait();
        producer.Wait();


        foreach (string s in _ProcessOutcome)
        {
            Console.WriteLine(s);
        }
    }

    private void FooBar(string aItem)
    {
        Console.WriteLine($"{DateTime.Now:mm:ss.fff}  FooBar - {aItem}");
        Thread.Sleep(500);
        _ProcessOutcome.Add(aItem + "XX");
        Console.WriteLine($"{DateTime.Now:mm:ss.fff} /FooBar - {aItem}");

    }
}

产生以下控制台输出:

06:44.090  Produce - 2
06:44.090  /Produce - 2
06:44.090  Produce - 3
06:44.090  /Produce - 3
06:44.090  Produce - 4
06:44.090  /Produce - 4
06:44.090  Produce - 5
06:44.090  /Produce - 5
06:44.090  Produce - 6
06:44.090  /Produce - 6
06:44.091  Produce - 7
06:44.091  /Produce - 7
06:44.091  Produce - 8
06:44.091  /Produce - 8
06:44.091  Produce - 9
06:44.091  /Produce - 9
06:44.091  Produce - CompleteAdding
06:44.091  Produce - /CompleteAdding
06:44.126  FooBar - 3
06:44.126  FooBar - 4
06:44.126  FooBar - 1
06:44.126  FooBar - 0
06:44.126  FooBar - 2
06:44.126  FooBar - 5
06:44.126  FooBar - 6
06:44.126  FooBar - 7
06:44.627 /FooBar - 1
06:44.627 /FooBar - 2
06:44.627 /FooBar - 4
06:44.628  FooBar - 9
06:44.627 /FooBar - 0
06:44.627 /FooBar - 6
06:44.627 /FooBar - 5
06:44.627 /FooBar - 3
06:44.627 /FooBar - 7
06:44.627  FooBar - 8
06:45.128 /FooBar - 9
06:45.129 /FooBar - 8
06:45.129  Consume - CompleteAdding
06:45.129  Consume - /CompleteAdding
1XX
0XX
2XX
4XX
5XX
6XX
3XX
7XX
9XX
8XX
Finish...
  1. 但是,我的FooBar()使用者仅在生产者完成后才开始运行。我似乎无法弄清楚的是,如何使消费者在获取内容后立即处理_ProcessBuffer?
  2. 我猜我的Paralell.ForEach()是1的元凶。那么,如何重构事物,以便可以运行多个使用者(线程)?最终,我想要一个生产者和多个消费者。

0 个答案:

没有答案