为了提供可以依次排队并执行async方法的生产者-消费者功能,我正在尝试实现一个异步队列。我注意到在大型应用程序中使用它的主要性能问题。
async Task Loop() {
while (true) {
if (!_blockingCollection.TryTake(out var func)) continue;
await func.Invoke();
}
}
生产方:
public void Add(Func<Task> func) {
_blockingCollection.Add(func);
}
当我用await func.Invoke()
代替func.Invoke().Wait()
而不是正确等待它时,性能会大大提高。
为什么? 使用BlockingCollection的异步队列是个坏主意吗?
什么是更好的选择?
为什么?
问题中没有足够的信息来提供答案。
正如其他人所指出的那样,循环当前存在消耗CPU的旋转问题。
同时,我至少可以回答这一部分:
使用BlockingCollection的异步队列是个坏主意吗?
是
什么是更好的选择?
使用异步兼容队列。例如,TPL Dataflow中的Channels
或BufferBlock
/ ActionBlock
。
使用频道的示例:
async Task Loop() {
await foreach (var func in channelReader.ReadAllAsync()) {
await func.Invoke();
}
}
或者如果您尚未使用.NET Core:
async Task Loop() {
while (await channelReader.WaitToReadAsync()) {
while (channelReader.TryRead(out var func)) {
await func.Invoke();
}
}
}