Question

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?

Was it helpful?

Solution

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.)

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top