-1
\$\begingroup\$

I want to implement a custom TCP Client in Unity that has separate threads for sending and receiving certain messages. For sending, the Client is supposed to have a blocking queue, that

  • receives messages from other threads and
  • the message-sending thread polls messages from the queue and sends them - but blocks when the queue is empty.

In on .net 3.5 I do not have access to BlockingCollection.

I would have expected that some implementation existed. So far I have found implementation that simply lock on a queue, which from my understanding is not sufficient.

How could I implement this?

\$\endgroup\$
  • 5
    \$\begingroup\$ What have you tried so far? Brief search reveals dozen of implementations, duplicate SO questions included. \$\endgroup\$ – wondra Mar 28 '17 at 8:08
  • \$\begingroup\$ This question is not about game development, its about a library recommendation for c# \$\endgroup\$ – Peter Mar 28 '17 at 8:30
  • \$\begingroup\$ Sorry, I saw lots of questions related specifically to unity scripting, so i concluded this would be the right place to ask. Peter, so should i rather post it on Stackoverflow? \$\endgroup\$ – IARI Mar 28 '17 at 8:47
  • 1
    \$\begingroup\$ "c sharp blocking queue implementation", then is it just click the first link and copy-paste. There is even some discussion on blocking queue implementations. \$\endgroup\$ – wondra Mar 28 '17 at 9:20
  • 2
    \$\begingroup\$ @Lasse That won't do in this case. They don't want a concurrent queue, they want a blocking queue. The OP wants to suspend their message handling thread when the message queue is empty and have it resume the moment something is added to the queue. lock alone won't help with this. \$\endgroup\$ – Philipp Mar 28 '17 at 9:45
1
\$\begingroup\$

This implementation shared by Stephen Toub is literally the second Google search result for "blocking queue c#" so don't underestimate the value of doing your own research. ;)

Code reproduced below in case the link ever breaks. Comments are mine:

using System.Threading;
using System.Collections.Generic;

class BlockingQueue<T> : IEnumerable<T>    
{    
    private int _count = 0;

    private Queue<T> _queue = new Queue<T>();

    public T Dequeue()    
    {    
        lock (_queue)    
        {   
            // If we have items remaining in the queue, skip over this. 
            while (_count <= 0) 
            {
                // Release the lock and block on this line until someone
                // adds something to the queue, resuming once they 
                // release the lock again.
                Monitor.Wait(_queue);
            }

            _count--;

            return _queue.Dequeue();    
        }    
    }

    public void Enqueue(T data)    
    {    
        if (data == null) throw new ArgumentNullException(“data”);

        lock (_queue)    
        {    
            _queue.Enqueue(data);

            _count++;

            // If the consumer thread is waiting for an item
            // to be added to the queue, this will move it
            // to a waiting list, to resume execution
            // once we release our lock.
            Monitor.Pulse(_queue);    
        }    
    }

    // Lets the consumer thread consume the queue with a foreach loop.
    IEnumerator<T> IEnumerable<T>.GetEnumerator()    
    {    
        while (true) yield return Dequeue();    
    }    

    IEnumerator IEnumerable.GetEnumerator()    
    {    
        return ((IEnumerable<T>)this).GetEnumerator();    
    }    
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.