如何使一个生产者,两个消费者

本文关键字:两个 消费者 何使一 生产者 | 更新日期: 2023-09-27 17:50:13

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

我尝试了很多方法:阻塞收集,monitor.wait(进入,退出,脉冲),信号量,但似乎不能让它工作。

这里是线程的开始:

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

如何使一个生产者,两个消费者

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

Task.Factory.StartNew将使您的代码在不同的线程上执行。因此,从button1_Click开始,将启动3个线程,每个线程将通过任务工厂向线程池推送一个新任务。至少可以去掉一层。让我们说,为了现代化的缘故,删除线程的东西,坚持使用Task.Factory.StartNew,直接在事件处理程序。

根据这一点,下面的代码可能会做你想要的:

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()会从集合中删除read元素,因此只能读取一次。