0

I have a problem where there is a collection of objects (active animation class), inside a main object, which I'm iterating through it's 'ToList()' version on every interval.

I'm actually running an UpdateAnimations method, recursively, on the main item and all of it's sub items.

Sometimes I'm getting a "Object reference not set to an instance of an object" exception on one of the list's items. I really don't know why it happens...

I'm NOT inserting a null object to the original list and all of the actions that are made on the list - are made with a lock structure. I only have a few references to it, such as: Add, Remove and looping through it's 'ToList()' version.

These are all of my references of the problematic list (m_ActiveAnimations):

public void UpdateAnimations(double renderTime)
{
    lock (m_SubElements)
    {
        // Execute child animations (order is not important)
        foreach (var subElement in m_SubElements.ToList())
            subElement.UpdateAnimations(renderTime);
    }

    lock (m_ActiveAnimations)
    {
        // Execute local active animations
        foreach (var activeSeq in m_ActiveAnimations.ToList())
        {
            // Check if needs to be activated
            if (double.IsNaN(activeSeq.StartTime))
            {
                // Start animation
                activeSeq.StartTime = renderTime;
            }
            
            ...
            
            // Remove animation from active list
            m_ActiveAnimations.Remove(activeSeq);
        }
    }
    
    ...
}

The adding part:

m_ActiveAnimations.Add(new ActiveAnimation());

And it throws here:

if (double.IsNaN(activeSeq.StartTime))
{
   ...
}
Raz Vaknin
  • 21
  • 3
  • If you're certain that you're not adding any `null` elements, then it's possible that you *are* somehow manipulating `m_ActiveAnimations` outside of that lock -- multi-threaded access to lists can easily result in NREs – canton7 May 05 '21 at 08:26
  • I know what the exception means. I don't know what the source of it in this particular case so it doesn't answer it. – Raz Vaknin May 05 '21 at 08:27
  • 1
    The code shown here cannot cause this to happen, therefore the error must be elsewhere. – Matthew Watson May 05 '21 at 08:28
  • @canton7 Those are all of my references to the list, so no other place can access it, I guess.. :/ – Raz Vaknin May 05 '21 at 08:29
  • 1
    Is "The adding part" done in a `lock(m_ActiveAnimations)`? You haven't shown that. – canton7 May 05 '21 at 08:30
  • @MatthewWatson Do you think that if the main item is disposed from another thread while I'm looping it might cause this maybe? – Raz Vaknin May 05 '21 at 08:31
  • @canton7 Nope. It can be a problem? – Raz Vaknin May 05 '21 at 08:32
  • 2
    Yes, that's your problem. From my first comment: "*it's possible that you are somehow manipulating m_ActiveAnimations outside of that lock -- multi-threaded access to lists can easily result in NREs*" – canton7 May 05 '21 at 08:32
  • @canton7 So it can happen EVEN if I'm coping the original list with ToList method? – Raz Vaknin May 05 '21 at 09:16
  • 1
    Sure. `List` isn't thread-safe. If you call `ToList()` on it (which iterates over it) while another thread is adding an element, undefined things can happen. For example [here](https://source.dot.net/#System.Private.CoreLib/List.cs,203), the number of elements in the list is incremented before the new element is written: if you iterate the list between those two statements, you'll read a `null` instead of that new element – canton7 May 05 '21 at 09:20
  • @canton7 I didn't knew that. Thanks a lot, I will definitely take those advises! – Raz Vaknin May 05 '21 at 09:22

0 Answers0