如何使用线程和任务创建一个生产者和两个消费者?
我尝试了很多东西:阻止收集,监视。等待(进入,退出,脉冲),信号量,但似乎无法使其正常工作。
这是线程开始:
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
}
}
答案 0 :(得分: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()
会从集合中删除read元素,因此只能读取一次。