3

Basically I have a blockingcollection in my windows service application, each time I want to add 4 items to the collection then processing it.

The first round is okay, but the second round failed. The error is

The BlockingCollection has been marked as complete with regards to additions.

My code:

    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.

The main application code:

            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;
                }
            }

I realized that there was a code bc.CompleteAdding(); to block the further additions. So I commented out it, but it would not go to the second round block. It didn't reach the code Console.WriteLine("Blocking end"); It was same as my old thread.

Community
  • 1
  • 1
  • I can see `BlockingCollection` is passed as parameter to `ProcessCall` constructor. Is there any possibility that `ProcessCall` calls `bc.CompleteAdding();`? – Sriram Sakthivel Aug 08 '14 at 13:49
  • @SriramSakthivel, perhaps I can. But does it block the second round's additions? –  Aug 08 '14 at 13:52
  • That depends on when you call `CompleteAdding`. If second iteration runs after `CompleteAdding` called, you'll see this behavior. – Sriram Sakthivel Aug 08 '14 at 13:58
  • @SriramSakthivel, it doesn't work if I move `bc.CompleteAdding();` to ProcessCall. It is same as my old thread. The code doesn't reach `Blocking end` line. –  Aug 08 '14 at 14:13
  • 1
    There doesn't seem to be a 'ResetAdding' or whatever, so once you call `CompleteAdding()` you will need to recreate the whole collection. – TaW Aug 08 '14 at 16:07
  • @TaW,thanks. I posted my own answer under your help. –  Aug 08 '14 at 19:00

1 Answers1

0

By the hint from TaW, I recreated the collection in each iteration.

Each iteration has its own 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;
                }