如何让一个生产者,两个消费者?

时间:2014-03-14 14:33:26

标签: c#

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

我尝试了很多东西:阻止收集,监视。等待(进入,退出,脉冲),信号量,但似乎无法使其正常工作。

这是线程开始:

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

1 个答案:

答案 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元素,因此只能读取一次。