title: c# Threading Lock and Monitor
body: <p>I'm currently running into a problem with multithreading and accessing a static list. A static list holds all items with several properties. The items are identified with a <code>Guid</code>. A main work thread changes some properties for any item in the static list. The child threads all have their own <code>Guid</code>, with this <code>Guid</code> they read their own item in the static list. And after a specific event they remove their assigned element from the static list.</p>
  
  <p><a href="https://i.stack.imgur.com/sS1KS.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/sS1KS.png" alt="enter image description here"></a></p>
  
  <p>To get to the source I have broken down my code to the essential methods and classes. The work thread has the following simplified code</p>
  
  <pre><code>public void RunWork()
  {
      Random random = new Random();
      Int32 index = -1;
      while (!Kill)
      {
          Thread.Sleep(1);
          if (MainWindow.Clients != null)
          {
              index = random.Next(0, MainWindow.Clients.Count);
  
              MainWindow.Clients[index].State = MainWindow.RandomString(9);
          }
      }
  }
  </code></pre>
  
  <p>Each child thread has the following simplified code</p>
  
  <pre><code>public void RunChild()
  {
      Random random = new Random();
      while (!Kill)
      {
          Thread.Sleep(100);
          if (MainWindow.Clients.Any(x =&gt; x.Id == Id))
          {
              this.State = MainWindow.Clients.First(x =&gt; x.Id == Id).State;
          }
          Thread.Sleep(random.Next(50));
          if (random.Next(100) % 90 == 0)
          {
              Kill = true;
              MainWindow.Clients.RemoveAll(x =&gt; x.Id == Id);
          }
      }
  }
  </code></pre>
  
  <p>If a child removes itself from the <code>MainWindow.Clients</code> list the work thread throws a exception, that the index it is trying to access does not exist.</p>
  
  <p>I have added <code>lock</code> statments around every access of <code>MainWindow.Clients</code> but this does not prevent the work thread from accessing a deleted item. I have also tried <code>Monitor.Enter(MainWindow.Clients)</code> and <code>Monitor.Exit(MainWindow.Clients)</code> but with the same result as with <code>lock</code>.</p>
  
  <p>The static list <code>MainWindow.Clients</code> is created before any thread runs and never gets recreated or disposed.</p>
  
  <p>If the <code>lock</code> statement is set around this block of code in the <code>RunWork()</code> method</p>
  
  <pre><code>lock (MainWindow.Clients)
  {
      Thread.Sleep(1);
      if (MainWindow.Clients != null)
      {
          index = random.Next(0, MainWindow.Clients.Count);
  
          MainWindow.Clients[index].State = MainWindow.RandomString(9);
      }
  }
  </code></pre>
  
  <p>Why does it not block the child threads from changing the list between the lines 
  where the random index is set and the list gets accessed?</p>
  
  <p><strong>Update 1:</strong>
  The following code still throws a IndexOutOfRangeException at <code>MainWindow.Clients[index].State = MainWindow.RandomString(9);</code>:</p>
  
  <pre><code>public void RunWork()
  {
      Random random = new Random();
      Int32 index = -1;
      while (!Kill)
      {
          Thread.Sleep(1);
          if (MainWindow.Clients != null)
          {
              lock (MainWindow.Clients)
              {
                  index = random.Next(0, MainWindow.Clients.Count);
  
                  MainWindow.Clients[index].State = MainWindow.RandomString(9);
              }
          }
      }
  }
  
  public void RunChild()
  {
      Random random = new Random();
      while (!Kill)
      {
          Thread.Sleep(100);
          if (MainWindow.Clients.Any(x =&gt; x.Id == Id))
          {
              this.State = MainWindow.Clients.First(x =&gt; x.Id == Id).State;
          }
          Thread.Sleep(random.Next(50));
          if (random.Next(100) % 90 == 0)
          {
              Kill = true;
              lock (MainWindow.Clients)
              {
                  MainWindow.Clients.RemoveAll(x =&gt; x.Id == Id);
              }
          }
      }
  }
  </code></pre>
  
  <p><strong>Update 2:</strong> <a href="https://pastebin.com/raw/dzqec5JW" rel="nofollow noreferrer">Here</a> is the complete code for the quick sample application</p>
  
  <p><strong>Update 3:</strong> I have edited my code and wrapped all accesses of <code>MainWindow.Clients</code> with lock statements. But still the threads access the variable while it is locked:
  <a href="https://i.stack.imgur.com/A7Jgn.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/A7Jgn.png" alt="enter image description here"></a></p>