表观BufferBlock.Post/Receive/ReceiveAsync种族/错误 [英] Apparent BufferBlock.Post/Receive/ReceiveAsync race/bug
问题描述
的跨张贴到<一个href=\"http://social.msdn.microsoft.com/Forums/en-US/tpldataflow/thread/89b3f71d-3777-4fad-9c11-50d8dc81a4a9\">http://social.msdn.microsoft.com/Forums/en-US/tpldataflow/thread/89b3f71d-3777-4fad-9c11-50d8dc81a4a9
我知道......我真的不使用TplDataflow其最大潜力。 ATM我只是使用 BufferBlock
作为消息的安全传递队列,在生产者和消费者都以不同的速率运行。我看到一些奇怪的行为让我难倒如何
继续。
I know... I'm not really using TplDataflow to its maximum potential. ATM I'm simply using BufferBlock
as a safe queue for message passing, where producer and consumer are running at different rates. I'm seeing some strange behaviour that leaves me stumped as to how to
proceed.
private BufferBlock<object> messageQueue = new BufferBlock<object>();
public void Send(object message)
{
var accepted=messageQueue.Post(message);
logger.Info("Send message was called qlen = {0} accepted={1}",
messageQueue.Count,accepted);
}
public async Task<object> GetMessageAsync()
{
try
{
var m = await messageQueue.ReceiveAsync(TimeSpan.FromSeconds(30));
//despite messageQueue.Count>0 next line
//occasionally does not execute
logger.Info("message received");
//.......
}
catch(TimeoutException)
{
//do something
}
}
在code以上(这是一个2000行的分布式解决方案的一部分),发送
被周期性地调用每100ms左右。这意味着一个项目是发表
版,以的MessageQueue
大约10次。此验证。然而,偶尔似乎 ReceiveAsync
不超时内完成(即发表
不会导致 ReceiveAsync
来完成)和 TimeoutException异常
正在30秒后引发。在这一点上,<code> messageQueue.Count 是数百人。这是意想不到的。这个问题已经在发布过(1篇帖子/秒)的速率较慢的被观察和前1000个项目已穿过通常发生在 BufferBlock
。
In the code above (which is part of a 2000 line distributed solution), Send
is being called periodically every 100ms or so. This means an item is Post
ed to messageQueue
at around 10 times a second. This is verified. However, occasionally it appears that ReceiveAsync
does not complete within the timeout (i.e. the Post
is not causing ReceiveAsync
to complete) and TimeoutException
is being raised after 30s. At this point, messageQueue.Count
is in the hundreds. This is unexpected. This problem has been observed at slower rates of posting too (1 post/second) and usually happens before 1000 items have passed through the BufferBlock
.
所以,要解决这个问题,我使用下面的code,它的工作原理,但偶尔在接收时(由于上述发生的bug)导致1秒的延迟
So, to work around this issue, I am using the following code, which works, but occasionally causes 1s latency when receiving (due to the bug above occurring)
public async Task<object> GetMessageAsync()
{
try
{
object m;
var attempts = 0;
for (; ; )
{
try
{
m = await messageQueue.ReceiveAsync(TimeSpan.FromSeconds(1));
}
catch (TimeoutException)
{
attempts++;
if (attempts >= 30) throw;
continue;
}
break;
}
logger.Info("message received");
//.......
}
catch(TimeoutException)
{
//do something
}
}
这看起来像一个TDF竞争状态给我,但我不能得到的,为什么这不会在其他地方,我用发生底部 BufferBlock
以类似的方式。从 ReceiveAsync
实验改为接收
于事无补。我没有检查,但我想在隔离,code以上完美的作品。这是以TPL数据流简介 tpldataflow.docx 我在见过记录模式
This looks like a race condition in TDF to me, but I can't get to the bottom of why this doesn't occur in the other places where I use BufferBlock
in a similar fashion. Experimentally changing from ReceiveAsync
to Receive
doesn't help. I haven't checked, but I imagine in isolation, the code above works perfectly. It's a pattern I've seen documented in "Introduction to TPL Dataflow" tpldataflow.docx.
我能做些什么来得到这条底线?是否有可能有助于推断发生了什么的指标?如果我不能创建一个可靠的测试情况下,有什么更多的信息可以提供我?
What can I do to get to the bottom of this? Are there any metrics that might help infer what's happening? If I can't create a reliable test case, what more information can I offer?
帮助!
推荐答案
斯蒂芬似乎认为下面是解决方案
Stephen seems to think the following is the solution
VAR M =等待messageQueue.ReceiveAsync();
var m = await messageQueue.ReceiveAsync();
而不是:
VAR M =等待messageQueue.ReceiveAsync(TimeSpan.FromSeconds(30));
var m = await messageQueue.ReceiveAsync(TimeSpan.FromSeconds(30));
可以证实或否认这一点?
Can you confirm or deny this?
这篇关于表观BufferBlock.Post/Receive/ReceiveAsync种族/错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!