Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I'm pretty sure <code>BlockingCollection&lt;T&gt;</code> can't do this, you'd have to roll your own. I came up with this:</p> <pre><code>class NotifyingCollection&lt;T&gt; { private ConcurrentQueue&lt;Action&lt;T&gt;&gt; _subscribers = new ConcurrentQueue&lt;Action&lt;T&gt;&gt;(); private ConcurrentQueue&lt;T&gt; _overflow = new ConcurrentQueue&lt;T&gt;(); private object _lock = new object(); public void Add(T item) { _overflow.Enqueue(item); Dispatch(); } private void Dispatch() { // this lock is needed since we need to atomically dequeue from both queues... lock (_lock) { while (_overflow.Count &gt; 0 &amp;&amp; _subscribers.Count &gt; 0) { Action&lt;T&gt; callback; T item; var r1 = _overflow.TryDequeue(out item); var r2 = _subscribers.TryDequeue(out callback); Debug.Assert(r1 &amp;&amp; r2); callback(item); // or, optionally so that the caller thread's doesn't take too long ... Task.Factory.StartNew(() =&gt; callback(item)); // but you'll have to consider how exceptions will be handled. } } } public void TakeAsync(Action&lt;T&gt; callback) { _subscribers.Enqueue(callback); Dispatch(); } } </code></pre> <p>I've used the thread which calls <code>TakeAsync()</code> or <code>Add()</code> to serve as the callback thread. When you call <code>Add()</code> or <code>TakeAsync()</code> it will attempt to dispatch all the queued-up items to the queued-up callbacks. This way there's no thread created that just sits there sleeping, waiting to be signalled.</p> <p>That lock is kind of ugly, but you'll be able to enqueue and subscribe on multiple threads without locking. I couldn't figure out a way to do the equivalent of <em>only dequeue one if there's something available on the other queue</em> without using that lock.</p> <p><em>Note: I only tested this minimally, with a few threads.</em></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload