C# .NET BlockingCollection<;T>;CPU使用率
在四核系统中运行此程序将消耗25%的CPU功率。所以基本上有些东西在全速运转。我把范围缩小到了消费者,但按“x”键时,负载不会停止,这应该会终止我的消费者 我的代码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
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)可能是个好主意。我可能应该把这个问题换成另一个问题。