1

I'm working with large collections of objects and sequential reads of them. I found most questions along these lines refer to multi-threading, but I am more concerned with errors within the thread itself due to misuse of a distributable library.

A system within the library manages a potentially large collection of objects, at one point it performs a sequential read of this collection performing an operation on each element. Depending on the element implementation, which can be extended outside the library, an object may attempt to remove itself from the collection.

I would like that to be an option, but if this happens when the collection is being sequentially read this can lead to errors. I would like to be able to lock the contents of the collection while its being read and put any removal request on a schedule to be executed after the sequential read has finished. The removal request has to go through the system since objects do not have public access to the collection, I could just go with an isReading flag but I wonder if there is a more elegant construct.

Does C# or .NET provide a tool to do this? perhaps to lock the list contents so I can intercept removal requests during sequential reads? or would I have to implement that behavior from scratch for this scenario?

frenchie
  • 51,731
  • 109
  • 304
  • 510

2 Answers2

1

You may want to look into using the SynchronizedCollection<T> class in .NET 2.0+.

Alternatively, have a look at the answer to this question: What is the difference between SynchronizedCollection<T> and the other concurrent collections?

Community
  • 1
  • 1
Alastair Pitts
  • 19,423
  • 9
  • 68
  • 97
  • I'm under the impression that SynchronizedCollection is aimed at multi-threading sync and carries too much overhead for my case, where all happens in the same thread during the read process. – user1658867 Sep 10 '12 at 02:07
0

You can use the next trick

List<T> collection;

for(int index = collection; index >= 0; --index)
{
  var item = collection[index];

  if(MUST BE DELETED)
  {
    collection.RemoveAt(index); // this is faster
    OR
    collection.Remove(item);
  }
}

this code will not crash at collection modified and will process each item of collection

Viacheslav Smityukh
  • 5,652
  • 4
  • 24
  • 42
  • This approach is sort of what I planned on doing as the "implement from scratch" option. The note that RemoveAt is faster is useful, but I was more concerned about an elegant way of establishing the "MUST BE DELETED" condition in a way that prevents misuse. – user1658867 Sep 10 '12 at 02:06
  • There is no way to implement it nice and clear. The second solution is store all items whitch should be deleted in the separate collection. And delete them in the next loop. – Viacheslav Smityukh Sep 10 '12 at 02:17
  • The provided code is very fast and stable, I'm using it for years. – Viacheslav Smityukh Sep 10 '12 at 02:18
  • If you have an event that will cause more than 1 object to be removed from the list then your code needs to be aware of this too. What I do, in this case, is to copy the list/array I'll be enumerating over with something like `foreach (var item in itemList.ToArray())` and then just below this, I'll do something along the lines of `if (itemList.Contains(item))` to make sure I'm working on something that still exists. I don't know how effecient this it, but I've only used this approach for relatively small collections. – Joe Shanahan Sep 10 '12 at 22:01
  • Your method is hicost and should not be used for the big collections. – Viacheslav Smityukh Sep 10 '12 at 22:07