如何使一个生产者,两个消费者
本文关键字:两个 消费者 何使一 生产者 | 更新日期: 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元素,因此只能读取一次。