【问题标题】:Consumer/Producer with BlockingCollection appears slow使用 BlockingCollection 的消费者/生产者看起来很慢
【发布时间】:2014-07-15 17:11:00
【问题描述】:

我正在通过下面的“生产者”从外部套接字连接获取数据。

我将数据放入BlockingCollection,然后由消费者读取。如果消费者在固定期限内没有收到数据,它无论如何都会触发,这样我的ProcessDataOnGrid 就会在数据到达时或至少在 x 毫秒后执行某些操作。

问题是我已经读到BlockingCollection 是首选的方法,但是看起来很慢。

从获取外部数据到致电ProcessDataOnGrid 之间平均需要 150 毫秒。我是在错误地使用它,还是有更好的方法来等待数据但仅在固定的时间段内等待?

public BlockingCollection<TickRecord> trPipe = new BlockingCollection<TickRecord>();

制作人:

public void ProcessMarketData(string key, string intraMessage)
{
    //////////
    //   Gets External data from intraMessage
    ////////////
    try
    {
        if (GRID!=null)
        {
            TickRecord tr = new TickRecord(intraMessage);

            while ( ! AddToFeedPipe(key, tr) )
            {
                Thread.Sleep(1000);
            }
        }
    }
    catch (Exception e)
    {
    }
  }
}

public bool AddToFeedPipe(string key, TickRecord tr)
{
        try
        {
            foreach (var s in cReader.STREAMS)
            {
                if (s.key == key)
                {
                    s.trPipe.Add(tr);
                    return true;
                }
            }

            return false;
        }
        catch (Exception)
        {
            return false;
        }
}

消费者:

public void Read()
{
    DateTime DTNOW = DateTime.UtcNow;

    TimeSpan gridNextTS = G.gridNextDT.Subtract(DTNOW);

    try
    {
        if (trPipe.TryTake(out tr,gridNextTS) == false)
        {
            tr = trGAP;
        }
        else if (tr == null)
        {
            EOF = true;
            return;
        }

        ProcessDataOnGrid(tr);
    }
    catch (Exception e)
    {
        tr = null;
        EOF = true;
        return;
    }
}

【问题讨论】:

  • BlockingCollection&lt;T&gt; 没有 Add 的重载,它会返回一个布尔值,所以我无法绕过你的 while ( ! trPipe.Add( tr) ) 行。
  • @KirillShlenskiy 你是对的!我试图简化这个问题的例子。我现在已经编辑以显示更接近我实际的代码。
  • 你的BlockingCollection&lt;T&gt; 在这里绝对没有错。它的性能足迹非常小。你的TryTake 逻辑看起来也是正确的,即使它有点不合常规。我倾向于责怪Thread.Sleep,它似乎用于线程同步目的(如果我在这里错了,请纠正我),但这样做会引入 巨大 延迟并且通常是不正确的工作的工具。不过也可能是别的东西:如果不看其余代码就很难分辨。
  • sleep() 仅在管道尚未送入时才真正在开始时被调用。在正常运行期间它不会被触发。
  • 这很难诊断,特别是如果您没有显示重现问题的实际代码段。我的意思是,你想让它简洁是件好事,但如果你设法创建一个最小的工作示例来展示你的问题,那就更好了。

标签: c# performance blockingcollection


【解决方案1】:

BlockingCollection 并不慢。我有另一个线程竞争相同的资源。

非常感谢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多