views:

100

answers:

5

I want to safely iterate(not get a collection was changed during iteration) through an array that can be changed by another thread. What's the best way I can do it?

+4  A: 

Make a copy? I guess it depends on whether you want your iteration to be a 'snapshot in time' or if you want to see the changes 'live'. The latter can get pretty dicey.

n8wrl
there is a way to iterate and get live changes?
Chen Kinnrot
+2  A: 

What do you mean by "safely"? Do you mind seeing a mixture of old and new values? If so, you can just iterate using foreach. (This is for two reasons: firstly, arrays don't have an internal "version number" like List<T> does, so the iterator can't detect that the array has changed. Secondly, using foreach on a type known to be an array in C# causes the compiler to use the length and indexer anyway, rather than using an iterator.)

If you want to get a snapshot, you basically need to take a copy of the array and iterate over that.

EDIT: I was assuming you wanted concurrency. (I'm not sure why I assumed that.) I agree with the other answers that locking is an alternative - but you need to lock around the whole iteration, e.g.

lock (someLock)
{
    foreach (var x in array)
    {
        // Stuff
    }
}

and likewise in the writing thread:

lock (someLock)
{
    array[0] = "foo";
}

(You could lock on the array itself, but I generally prefer to have private locks.)

Jon Skeet
If you've got an iterator to a collection and that collection changes (on another thread) doesn't the iterator throw?
Will
@Will: For most collections, yes - but not for arrays.
Jon Skeet
Interesting... I'd think System.Array would provide this just so that behavior would be widely implemented.
Will
@Will: I suspect the reason is that arrays are pretty low-level, close-to-the-metal types - incrementing a version field every time a change is made could significantly reduce performance.
Jon Skeet
List<T> has internal version no for values :o
noob.spt
@noob2487: Yes it does - any time you set a value using the indexer, it updates the list's version number. There isn't one *per* value, but it does have one which takes account of setting values.
Jon Skeet
if i lock the code it doesnt make sure that another code on another thread willl not change the collection
Chen Kinnrot
A: 

You probably want to use syncronized access. You can lock the array for the time you need to parse it and the time you add/remove items.

You could use lock/unlock (http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.80).aspx

Dan Cristoloveanu
A: 

For ultra safeness, you could lock all access to the array while you are iterating through it. Its the only way to ensure that the array you are iterating through is fully up to date..

Mongus Pong
+2  A: 

Target 4.0 and use one of the many thread safe collections.

Will