title: Intermittent IndexOutOfRangeException in ChannelServices.RegisteredChannels
body: <p>We've been getting this exception intermittently in our applications:</p>
  
  <pre><code>System.IndexOutOfRangeException: Index was outside the bounds of the array.
  at System.Runtime.Remoting.Channels.ChannelServices.get_RegisteredChannels()
  at ProductCacheServiceClient.getProductCacheServiceProvider(DataServiceConnectionDetails connOptions)
  </code></pre>
  
  <p>Since it's intermittent and we call this quite a lot (in a web app, so can be concurrent) I thought maybe it was a threading issue but I've had a look in <a href="http://referencesource.microsoft.com/#mscorlib/system/runtime/remoting/channelservices.cs,296" rel="nofollow"><code>ChannelServices.get_RegisteredChannels</code></a> and although this is interacting with a list of channels, it takes a copy of the reference and both <code>RegisterChannel</code> and <code>UnregisterChannel</code> appear to have locks, and replaced the list in one go.</p>
  
  <p>We're stumped... If the locks are working as advertised and the MSDN docs are correct (it says static members of this class are threadsafe) then what could cause an IndexOutOfRange inside this property?</p>
  
  <p><strong>Edit</strong>: I've managed to make a small console app that will intermittently (about 1 in 5 runs in my testing) throw this exception. Im compiling in VS 2015 Update 1 targeting .NET 4.5.2.</p>
  
  <pre><code>List&lt;Task&gt; tasks = new List&lt;Task&gt;();
  
  for (var i = 0; i &lt; 1000; i++)
  {
  
      var task = Task.Run(() =&gt;
      {
          var chanProps = new System.Collections.Hashtable();
          chanProps["name"] = "cacheServicesClient" + Guid.NewGuid().ToString();
          chanProps["username"] = "a";
          chanProps["password"] = "b";
          chanProps["domain"] = "c";
  
          var channelToReturn = new TcpChannel(chanProps, null, null);
          bool registered = false;
          foreach (var channelRegistered in ChannelServices.RegisteredChannels)
          {
              if (channelRegistered.ChannelName == channelToReturn.ChannelName)
              {
                  registered = true;
                  break;
              }
          }
  
          if (!registered)
          {
              ChannelServices.RegisterChannel(channelToReturn, true);
          }
      }).ContinueWith(t =&gt;
      {
          if (t.IsFaulted &amp;&amp; t.Exception != null)
          {
              t.Exception.Handle(e =&gt;
              {
                  Console.WriteLine(e.ToString());
                  return true;
              });
          }
      });
  
      tasks.Add(task);
  }
  
  Task.WaitAll(tasks.ToArray());
  </code></pre>
  
  <p>and here's the error when it crashes:</p>
  
  <pre><code>System.IndexOutOfRangeException: Index was outside the bounds of the array.
     at System.Runtime.Remoting.Channels.ChannelServices.get_RegisteredChannels()
     at ConsoleApplication1.Program.&lt;&gt;c.&lt;Main&gt;b__0_0() in C:\Work\Source\TestApps\ConsoleApplication1\Program.cs:line 28
     at System.Threading.Tasks.Task.Execute()
  Press any key to continue . . .
  </code></pre>