Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>First, read this article to understand why it's bad: <a href="http://blogs.msdn.com/b/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx" rel="nofollow">http://blogs.msdn.com/b/jaredpar/archive/2009/02/11/why-are-thread-safe-collections-so-hard.aspx</a></p> <p>Then, do it anyway like I did:</p> <pre><code>public abstract class ConcurrentCollection&lt;T&gt; : ICollection&lt;T&gt; { private List&lt;T&gt; List { get; set; } public ConcurrentCollection() { this.List = new List&lt;T&gt;(); } public T this[int index] { get { return this.List[index]; } } protected virtual void AddUnsafe(T item) { this.List.Add(item); } protected virtual void RemoveUnsafe(T item) { this.List.Remove(item); } protected virtual void ClearUnsafe() { this.List.Clear(); } public void Add(T item) { lock (this.List) { this.AddUnsafe(item); } } public bool Remove(T item) { lock (this.List) { this.RemoveUnsafe(item); return true; } } public void Clear() { lock (this.List) { this.ClearUnsafe(); } } public int Count { get { lock (this.List) { return this.List.Count; } } } public bool IsReadOnly { get { return false; } } public bool Contains(T item) { lock (this.List) { return this.List.Contains(item); } } public void CopyTo(T[] array, int arrayIndex) { lock (this.List) { this.List.CopyTo(array, arrayIndex); } } public IEnumerator&lt;T&gt; GetEnumerator() { return new ConcurrentEnumerator&lt;T&gt;(this.List, this.List); } IEnumerator IEnumerable.GetEnumerator() { throw new NotImplementedException("Abstract concurrent enumerators not implemented."); } } public class ConcurrentEnumerator&lt;T&gt; : IEnumerator&lt;T&gt; { private int Position = -1; private List&lt;T&gt; Duplicate; private object Mutex; private ICollection&lt;T&gt; NonConcurrentCollection; internal ConcurrentEnumerator(ICollection&lt;T&gt; nonConcurrentCollection, object mutex) { this.NonConcurrentCollection = nonConcurrentCollection; this.Mutex = mutex; lock (this.Mutex) { this.Duplicate = new List&lt;T&gt;(this.NonConcurrentCollection); } } public T Current { get { return this.Duplicate[this.Position]; } } object IEnumerator.Current { get { return this.Current; } } public bool MoveNext() { this.Position++; lock (this.Mutex) { while (this.Position &lt; this.Duplicate.Count &amp;&amp; !this.NonConcurrentCollection.Contains(this.Current)) { this.Position++; } } return this.Position &lt; this.Duplicate.Count; } public void Reset() { this.Position = -1; } public void Dispose() { } } // Standards have List as derived Collection... public class ConcurrentList&lt;T&gt; : ConcurrentCollection&lt;T&gt; { } </code></pre> <p>This code is still not fully safe, for instance the Count example may still crash, but it allows for iteration, adding and removing across threads. If you want to expose the mutex, do so, then lock around it for your other code constructs like count and contains.</p> <p>But it's still a bad idea.</p> <p><strong>Edit</strong>: Example usage.</p> <pre><code>ConcurrentList&lt;string&gt; list = new ConcurrentList&lt;string&gt;(); list.Add("hello"); list.Add("world"); list.Add("foo"); list.Add("bar"); foreach (string word in list) { if (word == "world") { list.Remove("bar"); // Will not crash the foreach! } Console.WriteLine(word); } </code></pre> <p>Output:</p> <pre><code>hello world foo </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