事件订阅已更改 - InvalidOperationException

Event subscription changed - InvalidOperationException

UI 元素可以订阅按下、按住或释放等事件。因此,我创建了一个对象变量来存储这些信息

        private Dictionary<TouchListenerType, List<Action<int, float, Vector2>>> touchData = new Dictionary<TouchListenerType, List<Action<int, float, Vector2>>>();

每个更新周期我都会遍历每个提供的输入并将其委托给订阅者。

        try
        {
            for (int currentTouchIndex = touchCollections.Count - 1; currentTouchIndex >= 0; currentTouchIndex--)
            {
                Vector2 position = MapInput(touchCollections[currentTouchIndex].Position);
                if (touchCollections[currentTouchIndex].State == TouchLocationState.Moved &&
                    touchData[TouchListenerType.Move].Count > 0)
                    touchData[TouchListenerType.Move].ForEach(d => d.Invoke(touchCollections[currentTouchIndex].Id, touchCollections[currentTouchIndex].Pressure, position));
                else if (touchCollections[currentTouchIndex].State == TouchLocationState.Pressed &&
                    touchData[TouchListenerType.Press].Count > 0)
                    touchData[TouchListenerType.Press].ForEach(d => d.Invoke(touchCollections[currentTouchIndex].Id, touchCollections[currentTouchIndex].Pressure, position));
                else if (touchCollections[currentTouchIndex].State == TouchLocationState.Released &&
                    touchData[TouchListenerType.Release].Count > 0)
                    touchData[TouchListenerType.Release].ForEach(d => d.Invoke(touchCollections[currentTouchIndex].Id, touchCollections[currentTouchIndex].Pressure, position));
            }
        } catch { } //Enumeration could have been changed

如果订阅者决定取消订阅或根据提供的输入添加另一个订阅,将抛出异常 System.InvalidOperationException,因为事件订阅者计数已被变了。到现在为止,我只是在块周围放了一个 try-catch。但我想避免原来的问题。

基于每个订阅者都能够在委托中 unsubscribe/subscribe 的事实,我无法使用信号量。此外,我想避免在每个更新周期都创建事件的副本,因为此应用程序在移动设备上 运行。我怎样才能解决这个问题?

也许 Concurrent Dictionary 就足够了?

您可能还需要实施 Custom Event Accessors

编辑:

错误是由 List<T>.ForEach 语句生成的,其中集合在迭代期间发生了更改。应该使用 for 循环来实现这一点。