Search Unity

Question InvalidOperationException: Collection was modified; enumeration operation may not execute.

Discussion in 'UI Toolkit' started by niel-archer, Sep 29, 2021.

  1. niel-archer

    niel-archer

    Joined:
    Nov 29, 2016
    Posts:
    17
    I have the following method:


    public void CheckInstalledMods()
    {
    string configText = File.ReadAllText(_dataPath + @"SavedMods/InstalledMods.cfg");

    // Destroy any previously created objects, before populating it again.
    modsList.Clear();

    // If there any mods found, we populate the list with them.
    if (configText.Length > 0)
    {
    installedMods = JsonHelper.FromJson<InstalledMod>(@configText);
    modsList.AddRange(installedMods);
    modsList.Sort();
    }
    else // If the file is less than 1, there are no mods found so we add a dummy entry saying the list is empty.
    {
    // FIX THIS
    installedMods = JsonHelper.FromJson<InstalledMod>(@NothingFoundJson);
    modsList.AddRange(installedMods);
    }
    }


    When the configText.Length > 0 is true it works exactly as expected. However when that fails the second modsList.AddRange throws the exception in the title. I have carefully checked the 'NothingFoundJson' and ensured it has no errors, so I am at a loss to see what the problems is.
     
    Last edited: Sep 29, 2021
  2. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Please post the full stack trace. Something is keeping an enumerator around when it shouldn't be.
     
  3. niel-archer

    niel-archer

    Joined:
    Nov 29, 2016
    Posts:
    17
    InvalidOperationException: Collection was modified; enumeration operation may not execute.
    System.Collections.Generic.List`1+Enumerator[T].MoveNextRare () (at <a4f9e7f5e7934738b65dad1344f8615e>:0)
    System.Collections.Generic.List`1+Enumerator[T].MoveNext () (at <a4f9e7f5e7934738b65dad1344f8615e>:0)
    UI.ModItem.BindEntry (UI.Mod entry) (at Assets/Scripts/UI/ModItem.cs:46)
    UI.ModManager.<OnEnable>b__38_2 (UnityEngine.UIElements.VisualElement e, System.Int32 i) (at Assets/Scripts/UI/ModManager.cs:371)
    UnityEngine.UIElements.CollectionViewController.BindItem (UnityEngine.UIElements.VisualElement element, System.Int32 index) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Controllers/CollectionViewController.cs:111)
    UnityEngine.UIElements.CollectionViewController.InvokeBindItem (UnityEngine.UIElements.ReusableCollectionItem reusableItem, System.Int32 index) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Controllers/CollectionViewController.cs:71)
    UnityEngine.UIElements.ListViewController.InvokeBindItem (UnityEngine.UIElements.ReusableCollectionItem reusableItem, System.Int32 index) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Controllers/ListViewController.cs:37)
    UnityEngine.UIElements.VerticalVirtualizationController`1[T].Setup (T recycledItem, System.Int32 newIndex, System.Boolean forceHide) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Virtualization/VerticalVirtualizationController.cs:147)
    UnityEngine.UIElements.FixedHeightVirtualizationController`1[T].Resize (UnityEngine.Vector2 size, System.Int32 layoutPass) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Virtualization/FixedHeightVirtualizationController.cs:108)
    UnityEngine.UIElements.BaseVerticalCollectionView.Resize (UnityEngine.Vector2 size, System.Int32 layoutPass) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Controls/BaseVerticalCollectionView.cs:866)
    UnityEngine.UIElements.BaseVerticalCollectionView.OnSizeChanged (UnityEngine.UIElements.GeometryChangedEvent evt) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Controls/BaseVerticalCollectionView.cs:1446)
    UnityEngine.UIElements.EventCallbackFunctor`1[TEventType].Invoke (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.PropagationPhase propagationPhase) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/EventCallback.cs:79)
    UnityEngine.UIElements.EventCallbackRegistry.InvokeCallbacks (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.PropagationPhase propagationPhase) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/EventCallbackRegistry.cs:353)
    UnityEngine.UIElements.CallbackEventHandler.HandleEvent (UnityEngine.UIElements.EventBase evt) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/EventHandler.cs:186)
    UnityEngine.UIElements.CallbackEventHandler.HandleEventAtTargetPhase (UnityEngine.UIElements.EventBase evt) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/EventHandler.cs:151)
    UnityEngine.UIElements.EventDispatchUtilities.PropagateEvent (UnityEngine.UIElements.EventBase evt) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/IEventDispatchingStrategy.cs:74)
    UnityEngine.UIElements.DefaultDispatchingStrategy.DispatchEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/DefaultDispatchingStrategy.cs:15)
    UnityEngine.UIElements.EventDispatcher.ApplyDispatchingStrategies (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, System.Boolean imguiEventIsInitiallyUsed) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:381)
    UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:344)
    UnityEngine.UIElements.EventDispatcher.ProcessEventQueue () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:306)
    UnityEngine.UIElements.EventDispatcher.OpenGate () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:270)
    UnityEngine.UIElements.EventDispatcherGate.Dispose () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:75)
    UnityEngine.UIElements.UIRLayoutUpdater.Update () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Renderer/UIRLayoutUpdater.cs:57)
    UnityEngine.UIElements.VisualTreeUpdater.UpdateVisualTreePhase (UnityEngine.UIElements.VisualTreeUpdatePhase phase) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/VisualTreeUpdater.cs:155)
    UnityEngine.UIElements.Panel.ValidateLayout () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Panel.cs:943)
    UnityEngine.UIElements.BaseVisualElementPanel.Update () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Panel.cs:577)
    UnityEngine.UIElements.RuntimePanel.Update () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/GameObjects/RuntimePanel.cs:47)
    UnityEngine.UIElements.UIElementsRuntimeUtility.UpdateRuntimePanels () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/UIElementsRuntimeUtility.cs:209)
    UnityEngine.UIElements.UIElementsRuntimeUtilityNative.UpdateRuntimePanels () (at /home/bokken/buildslave/unity/build/Modules/UIElementsNative/UIElementsUtility.bindings.cs:26)
     
  4. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Looks like the problem is somewhere in one of these methods:

     
  5. niel-archer

    niel-archer

    Joined:
    Nov 29, 2016
    Posts:
    17
    Many thanks.

    That allowed me to narrow down the problem. I had assumed the collection in question was modsList. This was only indirectly true as it is the source list for a ListView element. The actual problem was that I was modifying the hierarchy in a ListView element when the data binding was being done. So the collection in question was the ListView row, I think.

    Anyhow, I have re-architected the binding so that the element is not instantiated until after the changes are made. All seems good now.
     
  6. burningmime

    burningmime

    Joined:
    Jan 25, 2014
    Posts:
    845
    Wait data binding works at runtime now? WHAAAT? When did that happen?
     
  7. niel-archer

    niel-archer

    Joined:
    Nov 29, 2016
    Posts:
    17
    Ummm, may be I chose the wrong phrase there. The 'binding' of the List is done normally with the ListView(source, itemHeight, makeItem, bindItem). But the actual data is bound to the row at runtime by the bindItem callback. In my case, that is a method of the makeItem class so that I can set somw attribute depending on the data.