表观BufferBlock.Post/Receive/ReceiveAsync种族/错误 [英] Apparent BufferBlock.Post/Receive/ReceiveAsync race/bug

查看:235
本文介绍了表观BufferBlock.Post/Receive/ReceiveAsync种族/错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

跨张贴到<一个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 Posted 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆