C# .NET BlockingCollection<;T>;CPU使用率

C# .NET BlockingCollection<;T>;CPU使用率,c#,multithreading,asynchronous,blockingcollection,C#,Multithreading,Asynchronous,Blockingcollection,在四核系统中运行此程序将消耗25%的CPU功率。所以基本上有些东西在全速运转。我把范围缩小到了消费者,但按“x”键时,负载不会停止,这应该会终止我的消费者 我的代码 internal class TestBlockingCollectionConsumerProducer2 { private int _itemCount; internal void Run() { BlockingCollection<string> blockingCo

在四核系统中运行此程序将消耗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);
        }
    }
}
内部类TestBlockingCollectionConsumerProducer2
{
私有整数项计数;
内部无效运行()
{
BlockingCollection BlockingCollection=新建BlockingCollection();
//用于发出取消请求的令牌源。
CancellationTokenSource cts=新的CancellationTokenSource();
//等待控制台“x”的简单线程
Task.Factory.StartNew(()=>
{
if(Console.ReadKey().KeyChar=='x')
{
cts.Cancel();
}
});
//创始制作人
Task.Factory.StartNew(()=>product(blockingCollection,cts.Token));
//启动多个消费者
const int THREAD_COUNT=5;
对于(int i=0;iConsume(blockingCollection,cts.Token));
}
虽然(正确);
}
私有作废生成(BlockingCollection BlockingCollection、CancellationToken CancellationToken)
{
while(true)
{
对于(int i=0;i<10;i++)
{
blockingCollection.Add(string.Format(“Item{0}”,_itemCount++),cancellationToken);
}
Console.WriteLine(“添加了10项。当前队列长度:“+blockingCollection.Count”);
睡眠(10000);
}
}
私有无效消费(BlockingCollection BlockingCollection、CancellationToken CancellationToken)
{
尝试
{
foreach(blockingCollection.GetConsumingEnumerable(cancellationToken))中的字符串项
{
WriteLine(string.Format(“[{0}]使用者:消费:{1}”,Thread.CurrentThread.ManagedThreadId,item));
睡眠(2500);
}
}
捕获(操作取消异常)
{
Console.WriteLine(“[{0}]使用者:操作已被取消。”,Thread.CurrentThread.ManagedThreadId);
}
}
}
我的问题是:
1. 为什么CPU负载如此高?不应该阻塞GetConsumingEnumerable(),因此根本不使用CPU时间?
2. 为什么不在cts.Cancel()上停止?


问题不在于
阻止集合

它是带有
while(true)的无限循环。这在
Run
方法中做什么?这就是烧掉你的cpu的原因

我看到
product
方法不尊重
CancellationToken
。您应该在(!cancellationToken.IsCancellationRequested)
时使用
而不是无限循环


另外,对于
cts.Cancel
它确实取消了操作。如果由于某种原因无法正常工作,请提供复制问题的小而完整的程序。

问题不在于
BlockingCollection

它是带有
while(true)的无限循环。这在
Run
方法中做什么?这就是烧掉你的cpu的原因

我看到
product
方法不尊重
CancellationToken
。您应该在(!cancellationToken.IsCancellationRequested)
时使用
而不是无限循环


另外,对于
cts.Cancel
它确实取消了操作。如果由于某种原因无法正常工作,请提供复制问题的小而完整的程序。

否则,我将如何保持应用程序的活力?Run()是从Main()调用的-没有什么特别的。@lapsus请参阅:Task。WaitAll@lapsus这取决于你想让应用程序活多久。@lapsus:那么你让应用程序运行一个无限循环来让它活多久,那么你会惊讶于CPU被使用了吗?现在我很困惑。如果您使用的是Console应用程序,
Console.ReadLine()
将阻塞,使您能够准确控制关闭应用程序的时间,并且不会自行使用完整的处理器。我明白了。这个程序应该作为一个服务运行——所以我不希望它停止。这就是为什么我认为while(true)可能是个好主意。我可能应该把这个问题放在另一个问题上。否则我如何保持应用程序的活力?Run()是从Main()调用的-没有什么特别的。@lapsus请参阅:Task。WaitAll@lapsus这取决于你想让应用程序活多久。@lapsus:那么你让应用程序运行一个无限循环来让它活多久,那么你会惊讶于CPU被使用了吗?现在我很困惑。如果您使用的是Console应用程序,
Console.ReadLine()
将阻塞,使您能够准确控制关闭应用程序的时间,并且不会自行使用完整的处理器。我明白了。这个程序应该作为一个服务运行——所以我不希望它停止。这就是为什么我认为while(true)可能是个好主意。我可能应该把这个问题换成另一个问题。