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

我了解当您尝试在循环字典时更改字典时,字典会引发不同步异常。但是我正在循环的那一个只是被读取。

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

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;
    }
}


编辑:stacktrace:


  InvalidOperationException:不同步
  
  System.Collections.Generic.Dictionary'2 + Enumerator [Windows.Kinect.JointType,System.Boolean] .VerifyState()(位于/ 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()(位于/ Users / builduser / buildslave / mono-runtime-and-classlibs / build / mcs / class / corlib /System.Collections.Generic/Dictionary.cs:835)
  
  KinectFilterTesting.JointTypeSelectDisplay.UpdateDisplay()(在Assets / Scripts / Simon / JointTypeSelectDisplay.cs:146)
  
  KinectFilterTesting.JointTypeSelectDisplay.SetSelectedState(System.Collections.Generic.List'1类型,已选择布尔值)(位于Assets / Scripts / Simon / JointTypeSelectDisplay.cs:131)
  
  KinectFilterTesting.JointTypeSelectDisplay.SetRightArm(选中的布尔值)(位于Assets / Scripts / Simon / JointTypeSelectDisplay.cs:160)
  
  UnityEngine.Events.InvokableCall'1 [System.Boolean] .Invoke(System.Object [] args)(在C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:141)
  
  UnityEngine.Events.InvokableCallList.Invoke(System.Object []参数)(在C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:574)
  
  UnityEngine.Events.UnityEventBase.Invoke(System.Object []参数)(在C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:716)
  
  UnityEngine.Events.UnityEvent'1 [System.Boolean] .Invoke(布尔值arg0)(在C:/buildslave/unity/build/Runtime/Export/UnityEvent_1.cs:53)
  
  UnityEngine.UI.Toggle.Set(布尔值,布尔sendCallback)(位于C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:167)
  
  UnityEngine.UI.Toggle.Set(布尔值)(在C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:142)
  
  UnityEngine.UI.Toggle.set_isOn(布尔值)(在C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:136)
  
  UnityEngine.UI.Toggle.InternalToggle()(在C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:199)
  
  UnityEngine.UI.Toggle.OnPointerClick(UnityEngine.EventSystems.PointerEventData eventData)(位于C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:210)
  
  UnityEngine.EventSystems.ExecuteEvents.Execute(IPointerClickHandler处理程序,UnityEngine.EventSystems.BaseEventData eventData)(位于C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/EventSystem/ExecuteEvents.cs:52)
  
  UnityEngine.EventSystems.ExecuteEvents.Execute [IPointerClickHandler](UnityEngine.GameObject目标,UnityEngine.EventSystems.BaseEventData eventData,UnityEngine.EventSystems.EventFunction'1函数)(位于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时修改您的集合。同样,这也不会捕获在SelectedJoints运行时将条目添加到UpdateDisplay的情况,因此,如果您尚未这样做,则更频繁地运行UpdateDisplay可能是有意义的。

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

10-11 12:46