While I'm working on parallelism of our framework, I've confronted a strange condition which I can't imagine why! I simplified the situation to describe it easy. consider this code:
foreach(var person in personList)
{
if (person.Name == "Mehran")
break;
}
which the personList
is shared between multiple threads.
In what circumstances is it possible for person
to be null
and I get the NullReferenceException
for person.Name
?
As I know, the person is considered as a local variable here and if the we get into the foreach
block, so we have iterated the personList
successfully, so person
should not be null in any circumstances or any parallel scenario.
Even if the personList
is changed by another thread, or the referenced person
is disposed, the person
variable should have a value. Because no one has access to change where the person
is referenced to.
Is it any scenario to explain the situation?
As I know, the person is considered as a local variable here and if the we get into the foreach block, so we have iterated the personList successfully, so person should not be null in any circumstances or any parallel scenario.
Just because you're iterating over personList
successfully doesn't mean it doesn't contain any null values. For example:
List<Person> personList = new List<Person>();
personList.Add(null);
foreach (var person in personList)
{
// Here, person will be null
}
(Additionally, if anything is modifying the list, you're generally in trouble - they're not thread-safe in the face of writers - but I don't think that needs to be part of the problem.)
The variable is not modified. The iterator used to implement the foreach
construct is not thread safe:
From the documentation of List<T>.IEnumerable<T>.GetEnumerator()
found here:
An enumerator remains valid as long as the collection remains unchanged. If changes are made to the collection, such as adding, modifying, or deleting elements, the enumerator is irrecoverably invalidated and its behavior is undefined.
The enumerator does not have exclusive access to the collection; therefore, enumerating through a collection is intrinsically not a thread-safe procedure. To guarantee thread safety during enumeration, you can lock the collection during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization.
Default implementations of collections in the
System.Collections.Generic
namespace are not synchronized.
You should always lock lists while iterating over them if the possibility that another thread might modify the list exists.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With