Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>You are right. Calling <code>WaitOne</code> inside a lock could lead to a deadlock. And the check to see if the list is empty needs to be done inside the lock otherwise there could be a race with another thread trying to remove an item. Now, your code looks suspiciously like the producer-consumer pattern which is usually implemented with a blocking queue. If you are using .NET 4.0 then you can take advantage of the <a href="http://msdn.microsoft.com/en-us/library/dd267312.aspx" rel="nofollow">BlockingCollection</a> class. </p> <p>However, let me go over a couple of ways you can do it youself. The first uses a <code>List</code> and a <code>ManualResetEvent</code> to demonstrate how this could be done using the data structures in your question. Notice the use of a <code>while</code> loop in the <code>Take</code> method.</p> <pre><code>public class BlockingJobsCollection { private List&lt;Job&gt; m_List = new List&lt;Job&gt;(); private ManualResetEvent m_Signal = new ManualResetEvent(false); public void Add(Job item) { lock (m_List) { m_List.Add(item); m_Signal.Set(); } } public Job Take() { while (true) { lock (m_List) { if (m_List.Count &gt; 0) { Job item = m_List.First(); m_List.Remove(item); if (m_List.Count == 0) { m_Signal.Reset(); } return item; } } m_Signal.WaitOne(); } } } </code></pre> <p>But this not how I would do it. I would go with the simplier solution below with uses <code>Monitor.Wait</code> and <code>Monitor.Pulse</code>. <code>Monitor.Wait</code> is useful because it <em>can</em> be called inside a lock. In fact, it is <em>suppose</em> to be done that way.</p> <pre><code>public class BlockingJobsCollection { private Queue&lt;Job&gt; m_Queue = new Queue&lt;Job&gt;(); public void Add(Job item) { lock (m_Queue) { m_Queue.Enqueue(item); Monitor.Pulse(m_Queue); } } public Job Take() { lock (m_Queue) { while (m_Queue.Count == 0) { Monitor.Wait(m_Queue); } return m_Queue.Dequeue(); } } } </code></pre>
 

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