简体   繁体   中英

.NET BlockingCollection<T> CPU usage

Running this program will chew up 25% CPU power in a four cores system. So basically something is running at full thrust. I narrowed it down to the consumer however the load doesn't stop on pressing "x" which should terminate my consumers.

my code

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

My question is:
1. Why is the CPU load so high? Shouldn't GetConsumingEnumerable() block and therefore use no CPU time at all?
2. Why doesn't it stop on cts.Cancel()?

Problem isn't with the BlockingCollection .

It is the infinite loop with while (true); . What this is doing in Run method? That's what burning your cpu.

I see Produce method doesn't respect the CancellationToken . Instead of infinite loop, you should be using while (!cancellationToken.IsCancellationRequested) .

Also, for cts.Cancel it indeed cancels the operation. If that doesn't works for some reason, please provide small but complete program which reproduces the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM