I've seen this piece of code from one of the jetbrain's team :
Looking at this code :
object myLock = new object()
public IEnumerable<int> Values()
{
lock (myLock)
{
for (var i=0;i<10;i++)
yield return i;
}
}
public void Test()
{
foreach (var value in Values())
{
DoHugeJob(value);
}
}
void Main()
{
Test();
}
Question:
What is the scope of the lock
?
If you mean in terms of time - the lock will be aquired when MoveNext()
is first called, and will be released either when MoveNext()
has been called for the 11th time (i.e. when the loop completes) or when the iterator is disposed.
For example:
var iterable = Values();
// Lock is *not* acquired yet...
foreach (var item in iterable.Take(5)) {
// Lock has been acquired
}
// Lock has been released even though we didn't get to the
// end of the loop, because foreach calls Dispose
In general it's a bad idea to lock in iterator blocks precisely because of this - you really want to lock for a short, easily-understood period of your program.
See more on this question at Stackoverflow