.NET BlockingCollection <t> CPU使用率

时间:2015-04-23 09:39:30

标签: c# multithreading asynchronous blockingcollection

运行此程序将在四核系统中咀嚼25%的CPU功率。所以基本上一些东西正在全力以赴。我把它缩小到消费者,然而按下“x”时负载不会停止,这应该终止我的消费者。

我的代码

internal class TestBlockingCollectionConsumerProducer2
{
    private int _itemCount;

    internal void Run()
    {
        BlockingCollection<string> blockingCollection = new BlockingCollection<string>();

        // The token source for issuing the cancelation request.
        CancellationTokenSource cts = new CancellationTokenSource();

        // Simple thread waiting for a Console 'x'
        Task.Factory.StartNew(() =>
        {
            if (Console.ReadKey().KeyChar == 'x')
            {
                cts.Cancel();
            }
        });

        // start producer
        Task.Factory.StartNew(() => Produce(blockingCollection, cts.Token));

        // start multiple consumers
        const int THREAD_COUNT = 5;
        for (int i = 0; i < THREAD_COUNT; i++)
        {
            Task.Factory.StartNew(() => Consume(blockingCollection, cts.Token));
        }

        while (true);
    }

    private void Produce(BlockingCollection<string> blockingCollection, CancellationToken cancellationToken)
    {
        while (true)
        {
            for (int i = 0; i < 10; i++)
            {
                blockingCollection.Add(string.Format("Item {0}", _itemCount++), cancellationToken);
            }

            Console.WriteLine("Added 10 items. Current queue length:" + blockingCollection.Count);
            Thread.Sleep(10000);
        }
    }

    private void Consume(BlockingCollection<string> blockingCollection, CancellationToken cancellationToken)
    {
        try
        {
            foreach (string item in blockingCollection.GetConsumingEnumerable(cancellationToken))
            {
                Console.WriteLine(string.Format("[{0}] Consumer: Consuming: {1}", Thread.CurrentThread.ManagedThreadId, item));
                Thread.Sleep(2500);
            }
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("[{0}] Consumer: Operation has been canceled.", Thread.CurrentThread.ManagedThreadId);
        }
    }
}
  

我的问题是:
  1. 为什么CPU负载如此之高?不应该GetConsumingEnumerable()阻塞,因此根本不使用CPU时间?
  2. 为什么不在cts.Cancel()停止?

1 个答案:

答案 0 :(得分:5)

问题不在于BlockingCollection

这是while (true);的无限循环。这在Run方法中做了什么?这就是烧你的CPU的原因。

我看到Produce方法不尊重CancellationToken。您应该使用while (!cancellationToken.IsCancellationRequested)

而不是无限循环

此外,对于cts.Cancel,它确实取消了操作。如果由于某种原因不起作用,请提供小而完整的程序来重现问题。