【问题标题】:Can't add items to the collection in the second round无法在第二轮中将项目添加到集合中
【发布时间】:2014-08-08 13:43:42
【问题描述】:

基本上我的 Windows 服务应用程序中有一个阻塞集合,每次我想向集合中添加 4 个项目然后对其进行处理。

第一轮还可以,第二轮失败了。 错误是

BlockingCollection 在添加方面已被标记为完成。

我的代码:

    public static BlockingCollection<Tuple<ChannelResource, string>> bc = new BlockingCollection<Tuple<ChannelResource, string>>();
    public static List<string> list = new List<string>(); // then add 100 items to it.

主要应用代码:

            ProcessCall pc = new ProcessCall(OvrTelephonyServer, bc);
            while (true)
            {
                ThreadEvent.WaitOne(waitingTime, false);

                lock (SyncVar)
                {
                    Console.WriteLine("Block begin");
                    for (int i = 0; i < 4; i++)
                    {
                        var firstItem = list.FirstOrDefault();
                        ChannelResource cr = OvrTelephonyServer.GetChannel();
                        bc.TryAdd(Tuple.Create(cr, firstItem));
                        list.Remove(firstItem);
                    }
                    bc.CompleteAdding();
                    pc.SimultaneousCall();
                    Console.WriteLine("Blocking end");
                    if (ThreadState != State.Running) break;
                }
            }

我意识到有一个代码bc.CompleteAdding(); 可以阻止进一步的添加。所以我把它注释掉了,但它不会进入第二轮区块。没有到达代码Console.WriteLine("Blocking end"); 和我的old thread.一样

【问题讨论】:

  • 我可以看到 BlockingCollection 作为参数传递给 ProcessCall 构造函数。有没有可能ProcessCall 调用bc.CompleteAdding();
  • @SriramSakthivel,也许我可以。但它会阻止第二轮的补充吗?
  • 这取决于您何时致电CompleteAdding。如果在调用 CompleteAdding 之后运行第二次迭代,您将看到此行为。
  • @SriramSakthivel,如果我将 bc.CompleteAdding(); 移动到 ProcessCall,它将不起作用。这和我的旧线程一样。代码未到达Blocking end 行。
  • 似乎没有“ResetAdding”之类的,所以一旦你打电话给CompleteAdding(),你就需要重新创建整个集合。

标签: c# .net-4.0 blockingcollection


【解决方案1】:

根据 TaW 的提示,我在每次迭代中都重新创建了集合。

每次迭代都有自己的CompleteAdding()

                lock (SyncVar)
                {
                    bc = new BlockingCollection<Tuple<ChannelResource, string>>();
                    ProcessCall pc = new ProcessCall(OvrTelephonyServer, bc);
                    if (list.Count > 0)
                    {
                        Console.WriteLine("Block begin");
                        for (int i = 0; i < 4; i++)
                        {
                            if (list.Count > 0)
                            {
                                var firstItem = list.FirstOrDefault();
                                ChannelResource cr = OvrTelephonyServer.GetChannel();
                                bc.TryAdd(Tuple.Create(cr, firstItem));
                                list.Remove(firstItem);
                            }
                        }
                        bc.CompleteAdding();
                        pc.SimultaneousCall();
                        Console.WriteLine("Blocking end");
                    }
                    if (ThreadState != State.Running) break;
                }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    相关资源
    最近更新 更多