在处理 an answer 时至 this question ,我写了这个片段:
var buffer = new BufferBlock<object>();
var producer = Task.Run(async () =>
{
while (true)
{
await Task.Delay(TimeSpan.FromMilliseconds(100));
buffer.Post(null);
Console.WriteLine("Post " + buffer.Count);
}
});
var consumer = Task.Run(async () =>
{
while (await buffer.OutputAvailableAsync())
{
IList<object> items;
buffer.TryReceiveAll(out items);
Console.WriteLine("TryReceiveAll " + buffer.Count);
}
});
await Task.WhenAll(consumer, producer);
生产者应每 100 毫秒将项目发送到缓冲区,而消费者应清除缓冲区中的所有项目并异步等待更多项目出现。
实际发生的是生产者清除所有项目一次,然后再也不会超出 OutputAvailableAsync
。如果我将消费者切换为一件一件地移除元素,它会按异常(exception)情况工作:
while (await buffer.OutputAvailableAsync())
{
object item;
while (buffer.TryReceive(out item)) ;
}
我是不是误会了什么?如果不是,问题是什么?
最佳答案
这是 SourceCore
中的一个错误,被 BufferBlock
内部使用。它的 TryReceiveAll
方法不会打开 _enableOffering
bool 数据成员,而 TryReceive
会。这导致从 OutputAvailableAsync
返回的任务永远不会完成。
这是一个最小的复制:
var buffer = new BufferBlock<object>();
buffer.Post(null);
IList<object> items;
buffer.TryReceiveAll(out items);
var outputAvailableAsync = buffer.OutputAvailableAsync();
buffer.Post(null);
await outputAvailableAsync; // Never completes
我刚刚用 this pull request 在 .Net 核心存储库中修复了它.希望修复程序很快就会出现在 nuget 包中。
关于c# - BufferBlock 在 TryReceiveAll 之后与 OutputAvailableAsync 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25339029/