【问题标题】:How to make one producer, two consumers?如何让一个生产者,两个消费者?
【发布时间】:2014-04-19 22:02:48
【问题描述】:

如何用线程和任务创建一个生产者和两个消费者?

我尝试了很多方法:阻塞收集、monitor.wait(enter,exit,pulse)、信号量,但似乎无法正常工作。

这里是线程开始:

private void button1_Click(object sender, EventArgs e)
{
    Thread Producer = new Thread(new ThreadStart(Task_Producer));
    Thread Consumer = new Thread(new ThreadStart(Task_Consumer));
    Thread Consumer2 = new Thread(new ThreadStart(Task_Consumer2));
    Producer.start();
    Consumer.start();
    Consumer2.start();
}

这里是线程:

private Task task1;
private Task task2;
private Task task3;
void Task_Producer()
{
task1 = Task.Factory.StartNew(Producer_t);
}
void Task_Consumer()
{
task2 = Task.Factory.StartNew(Consumer_t);
}
void Task_Consumer2()
{
task3 = Task.Factory.StartNew(Consumer_t2);
}

这是任务:

int i=0;
int how_much_numbers=1000;
int number=0;
private void Producer_t()
{
   for (i = 0; i < how_much_numbers;i++)  
    {
     //number=random number;
    }
}
private void Consumer_t()
{
   while (i<how_much_numbers)
        {
        //Check if number is fibonaci
        }
}
private void Consumer_t2()
{
   while (i<how_much_numbers)
        {
        //Check if number is primary
        }
}

【问题讨论】:

  • 我尝试生成随机数,当与其他任务检查随机数是否是主要的以及写入文件时,与其他任务检查是否是斐波那契并写入文件。需要以某种方式生成随机,等待时,检查是否主要和斐波那契以及继续生成数字时。
  • 是什么让消费者不会错过一系列随机数?如何通知消费者有新号码可供消费?
  • 这里是全局变量号,也是全局 i。我们可以在此类中的任何功能上联系到谁。但我不知道该怎么做,这里需要在随机数任务和其他继续随机任务作业中以某种方式等待。 en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem
  • 你为什么要启动新线程只是为了启动任务?
  • 我认为我需要线程和任务。这是我的错误:/

标签: c# task


【解决方案1】:

在这个示例中,线程和任务混合在一起,这比错误更糟糕,就像我的老师所说的那样没用;-)

Task.Factory.StartNew 将使您的代码在不同的线程上执行。所以从button1_Click开始,会启动3个线程,每个线程都会通过任务工厂向线程池推送一个新任务。至少可以去除一层。假设,为了现代性,删除线程内容并直接在事件处理程序中坚持Task.Factory.StartNew

根据this,下面的代码可能会做你想做的事:

public class ProducerConsumerTest
{
    private readonly BlockingCollection<int> _randomNumbersForFibonacci = new BlockingCollection<int>(10);
    private readonly BlockingCollection<int> _randomNumbersForPrime = new BlockingCollection<int>(10);

    int i = 0;
    int how_much_numbers = 20;
    int number = 0;
    private void Producer_t()
    {
        var random = new Random();

        for (i = 0; i < how_much_numbers; i++)
        {
            var randomNumber = random.Next();

            _randomNumbersForFibonacci.Add(randomNumber);
            _randomNumbersForPrime.Add(randomNumber);
        }
    }
    private void Consumer_t()
    {
        foreach (var randomNumber in _randomNumbersForFibonacci.GetConsumingEnumerable())
        {
            //Check if number is fibonaci
            Console.Out.WriteLine("IsFibonacci({0})", randomNumber);
        }
    }
    private void Consumer_t2()
    {
        foreach (var randomNumber in _randomNumbersForPrime.GetConsumingEnumerable())
        {
            //Check if number is primary
            Console.Out.WriteLine("IsPrime({0})", randomNumber);
        }
    }

    public void Run()
    {
        var producingTask = Task.Factory.StartNew(Producer_t);

        var fibonacciTask = Task.Factory.StartNew(Consumer_t);

        var primeTask = Task.Factory.StartNew(Consumer_t2);
    }
}

但是您必须复制集合才能让两个任务分析每个生成的数字,因为遍历 .GetConsumingEnumerable() 会从集合中删除读取元素,因此只能读取一次。

【讨论】:

  • 好吧,我想对此表示赞同,因为您基本上是对的,但最好将此作为评论。
  • 感谢您的回答。我明白,我只需要使用线程或任务。但是如何在任务等待时与第一个任务生成随机数,在其他任务中检查数字是否是主要的,而在其他任务中是否是斐波那契以及何时继续生成数字?
  • @crush :暂时同意。我正在详细说明,现在我知道了目的:-)
  • 谢谢,我会试试的:)
  • @dan51 您可能需要 Task.WhenAll(produceTask, fibonacciTask, primeTask) 让您的程序等待 3 个任务完成。
猜你喜欢
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2015-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多