Is yield return in C# thread-safe?

Albic picture Albic · Sep 4, 2009 · Viewed 9.7k times · Source

I have the following piece of code:

private Dictionary<object, object> items = new Dictionary<object, object>;
public IEnumerable<object> Keys
{
    get
    {
        foreach (object key in items.Keys)
        {
            yield return key;
        }
    }
}

Is this thread-safe? If not do I have to put a lock around the loop or the yield return?

Here is what I mean:

Thread1 accesses the Keys property while Thread2 adds an item to the underlying dictionary. Is Thread1 affected by the add of Thread2?

Answer

Jon Skeet picture Jon Skeet · Sep 4, 2009

What exactly do you mean by thread-safe?

You certainly shouldn't change the dictionary while you're iterating over it, whether in the same thread or not.

If the dictionary is being accessed in multiple threads in general, the caller should take out a lock (the same one covering all accesses) so that they can lock for the duration of iterating over the result.

EDIT: To respond to your edit, no it in no way corresponds to the lock code. There is no lock automatically taken out by an iterator block - and how would it know about syncRoot anyway?

Moreover, just locking the return of the IEnumerable<TKey> doesn't make it thread-safe either - because the lock only affects the period of time when it's returning the sequence, not the period during which it's being iterated over.