在处理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# - TryReceiveAll之后,带有OutputAvailableAsync的BufferBlock死锁,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25339029/