.NET BlockingCollection<T> CPU 用法
.NET BlockingCollection<T> CPU usage
运行 该程序将在四核系统中消耗 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);
}
}
}
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()?
问题不在于 BlockingCollection
。
就是和while (true);
的死循环。这是在 Run
方法中做什么?那就是燃烧你的 cpu.
我看到 Produce
方法不符合 CancellationToken
。您应该使用 while (!cancellationToken.IsCancellationRequested)
.
而不是无限循环
此外,对于cts.Cancel
它确实取消了操作。如果由于某种原因这不起作用,请提供可重现问题的小而完整的程序。
运行 该程序将在四核系统中消耗 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);
}
}
}
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()?
问题不在于 BlockingCollection
。
就是和while (true);
的死循环。这是在 Run
方法中做什么?那就是燃烧你的 cpu.
我看到 Produce
方法不符合 CancellationToken
。您应该使用 while (!cancellationToken.IsCancellationRequested)
.
此外,对于cts.Cancel
它确实取消了操作。如果由于某种原因这不起作用,请提供可重现问题的小而完整的程序。