以下代码的目标是拥有“热键”(缺少更好的词)。这样的热键是一个切换多个复选框的复选框。
我理解当您尝试在循环时更改字典时,字典会抛出不同步异常。但我正在循环的那个只是被读取。
我找到了一个解决方案,但我仍然对这导致异常的原因感兴趣。
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()(at / Users / builduser / buildslave / mono-runtime-and-classlibs / build / mcs /类/ 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 /类/ corlib / System.Collections.Generic / Dictionary.cs:835)
KinectFilterTesting.JointTypeSelectDisplay.UpdateDisplay()(在Assets / Scripts / Simon / JointTypeSelectDisplay.cs:146)
KinectFilterTesting.JointTypeSelectDisplay.SetSelectedState(System.Collections.Generic.List'1 types,Boolean selected)(在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)(at C:/buildslave/unity/build/Runtime/Export/UnityEvent.cs:141)
UnityEngine.Events.InvokableCallList.Invoke(System.Object [] parameters)(在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(Boolean arg0)(at 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)(at C:/buildslave/unity/build/Extensions/guisystem/UnityEngine.UI/UI/Core/Toggle.cs:210)
UnityEngine.EventSystems.ExecuteEvents.Execute(IPointerClickHandler handler,UnityEngine.EventSystems.BaseEventData eventData)(在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)(在C:/ buildslave / unity / build / Extensions / guisystem / UnityEngine.UI /的EventSystem / ExecuteEvents.cs:269)
UnityEngine.EventSystems.EventSystem:更新()
答案 0 :(得分:2)
概率是在另一个线程上修改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
。