c# - 为什么这会导致 InvalidOperationException : Out of sync?

标签 c# dictionary unity-game-engine

以下代码的目标是拥有“热键”(由于缺乏更好的词)。这样的热键是一个可以切换多个复选框的复选框。

据我所知,当您在循环遍历字典时尝试更改字典时,字典会抛出不同步异常。但我正在循环的那个只是被读取。

我找到了解决方案,但仍然对为什么会导致异常感兴趣。

public class JointTypeSelectDisplay
{
    public Dictionary<JointType, bool> SelectedJoints;  
    private Dictionary<JointType, JointTypeListElement> _jointToggles;

    private void UpdateDisplay()
    {
        foreach (var joint in SelectedJoints)
        {
            _jointToggles[joint.Key].SetState(SelectedJoints[joint.Key]);
        }
    }
}

public class JointTypeListElement
{
    public Toggle JointToggle;

    public void SetState(bool active)
    {
        JointToggle.isOn = active;
    }
}

编辑:堆栈跟踪:

InvalidOperationException: out of sync

System.Collections.Generic.Dictionary'2+Enumerator[Windows.Kinect.JointType,System.Boolean].VerifyState () (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:912)

System.Collections.Generic.Dictionary'2+Enumerator[Windows.Kinect.JointType,System.Boolean].MoveNext () (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:835)

KinectFilterTesting.JointTypeSelectDisplay.UpdateDisplay () (at Assets/Scripts/Simon/JointTypeSelectDisplay.cs:146)

KinectFilterTesting.JointTypeSelectDisplay.SetSelectedState (System.Collections.Generic.List'1 types, Boolean selected) (at Assets/Scripts/Simon/JointTypeSelectDisplay.cs:131)

KinectFilterTesting.JointTypeSelectDisplay.SetRightArm (Boolean selected) (at Assets/Scripts/Simon/JointTypeSelectDisplay.cs:160)

UnityEngine.Events.InvokableCall'1[System.Boolean].Invoke (System.Object[] args) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:141)

UnityEngine.Events.InvokableCallList.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:574)

UnityEngine.Events.UnityEventBase.Invoke (System.Object[] parameters) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:716)

UnityEngine.Events.UnityEvent'1[System.Boolean].Invoke (Boolean arg0) (at C:/buildslave/unity/build/Runtime/Export/UnityEvent_1.cs:53)

UnityEngine.UI.Toggle.Set (Boolean value, Boolean sendCallback) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:167)

UnityEngine.UI.Toggle.Set (Boolean value) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:142)

UnityEngine.UI.Toggle.set_isOn (Boolean value) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:136)

UnityEngine.UI.Toggle.InternalToggle () (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:199)

UnityEngine.UI.Toggle.OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:210)

UnityEngine.EventSystems.ExecuteEvents.Execute (IPointerClickHandler handler, UnityEngine.EventSystems.BaseEventData eventData) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)

UnityEngine.EventSystems.ExecuteEvents.Execute[IPointerClickHandler] (UnityEngine.GameObject target, UnityEngine.EventSystems.BaseEventData eventData, UnityEngine.EventSystems.EventFunction'1 functor) (at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:269)

UnityEngine.EventSystems.EventSystem:Update()

最佳答案

可能性是 SelectedJoints 正在另一个线程上被修改。解决此问题的最简单方法是复制键并迭代它们:

private void UpdateDisplay()
{
    List<JointType> joints = new List<JointType>(SelectedJoints.Keys);

    foreach (JointType joint in joints)
    {
        if(_jointToggles.ContainsKey(joint) && SelectedJoints.ContainsKey(joint))
            _jointToggles[joint].SetState(SelectedJoints[joint]);
    }
}

请注意,需要 if 条件,因为您的错误强烈表明您的集合正在执行 UpdateDisplay 时被修改。此外,这不会捕获在 UpdateDisplay 运行时将条目添加到 SelectedJoints 的情况,因此如果您更频繁地运行 UpdateDisplay 可能是有意义的还没有这样做。

关于c# - 为什么这会导致 InvalidOperationException : Out of sync?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30304815/

相关文章:

python - 双索引字典

c++ - 如何索引实体中基本组件列表中的所有派生组件

arrays - 在 Swift 中修改字典数组

dictionary - 编码一个 [String : Encodable] dictionary into JSON using JSONEncoder in Swift 4

c# - 为什么相机没有旋转面向第一个航路点?

android - 无法将 Unity Remote 5 连接到 unity(版本 2018.2.3f1)

c# - String.Format 和 log.DebugFormat 货币

c# - 如何拦截捕获 WinForms 应用程序中的 TAB 键?

c# - 使用给定的用户名在远程机器上安装 Windows 服务

c# - 如何使用 LINQ 求和?