更好地理解任务和调度

时间:2014-03-28 18:30:01

标签: c# task-parallel-library scheduled-tasks

我是关于任务,并行和调度等的新手。在这里我创建了两个blockingcollection。一个用于收集输入,另一个用于输出。我添加了100个项目。所以我认为它们的总数应该是100或0.或者它们的总和等于100。

但是我发现他们都是0.请帮助我用简单的语言理解这些概念。

    static void Main(string[] args)
    {
        new Program().run();
    }
    void run()
    {
        int threadCount = 4;
        Task[] workers = new Task[threadCount];

        Task.Factory.StartNew(consumer);
        // We can do other work in parallel
        for (int i = 0; i < threadCount; ++i)
        {
            int workerId = i;
            Task task = new Task(() => worker(workerId));
            workers[i] = task;
            task.Start();
        }

        for (int i = 0; i < 100; ++i)
        {
            Console.WriteLine("Queueing work item {0}", i);
            inputQueue.Add(i);
            Thread.Sleep(50);
        }

        Console.WriteLine("Stopping adding.");
        inputQueue.CompleteAdding();
        Console.WriteLine("The count in InputQueue= {0}", inputQueue.Count);// 0
        Task.WaitAll(workers);
        outputQueue.CompleteAdding();
        Console.WriteLine("The count in OutputQueue= {0}", outputQueue.Count); // 0
        Console.WriteLine("Done.");

        Console.ReadLine();
    }

    void worker(int workerId)
    {
        Console.WriteLine("Worker {0} is starting.", workerId);

        foreach (var workItem in inputQueue.GetConsumingEnumerable())
        {
            Console.WriteLine("Worker {0} is processing item {1}", workerId, workItem);
            Thread.Sleep(100);          // Simulate work.
            outputQueue.Add(workItem);  // Output completed item.
        }

        Console.WriteLine("Worker {0} is stopping.", workerId);
    }

    void consumer()
    {
        Console.WriteLine("Consumer is starting.");

        foreach (var workItem in outputQueue.GetConsumingEnumerable())
        {
            Console.WriteLine("Consumer is using item {0}", workItem);
            Thread.Sleep(25);
        }

        Console.WriteLine("Consumer is finished.");
    }

    BlockingCollection<int> inputQueue = new BlockingCollection<int>();
    BlockingCollection<int> outputQueue = new BlockingCollection<int>();
}

1 个答案:

答案 0 :(得分:3)

你有一个3阶段管道

run -- (inputQueue) -- worker -- (outputQueue) -- consumer

所有3个阶段同时运行,只要1个项目位于inputQueue,就可以立即取出并移至outputQueue,只要将一个项目放入outputQueue 1}}它可以立即取出并处理。

所以要计算100,你需要做

(100 - number of items "run" has put in to "inputQueue") + 
"inputQueue.Count" + 
some number between 0 and "threadCount" representing items that have been taken out of "inputQueue" but have not yet been put in "outputQueue" +
"outputQueue.Count" + 
the number of items "consumer" has taken out of "outputQueue"

由于您的线程和等待数量完全平衡,因此负载很可能是上面的公式0 + 0 + 4 + 0 + 96,其中最后4个元素等待在worker处理,其他所有已经处理过的按consumer。如果你做了一半的工作线程并使消费者花了4倍的时间来处理你就会有像0 + 48 + 2 + 25 + 25这样的数字,其中48个等待由工人处理,2个由工人处理,25个等待消费者处理,25已经由消费者处理。