收集被修改; 枚举操作可能无法执行

Use*_*979 0 c# wpf tabcontrol tabitem

我的TabControl中有多个TabItems; tabItem1,tabItem2,tabItem3 ......这些都是

CloseableTabItem.

如果我在tabItem1中添加一个节点并按一个按钮为该节点创建一个subGraph模型,那么

同一节点应该在tabItem2中出现一个按钮; 以便

tabItem2-Header = nodeName和nodeName = tabItem1-Header.

如果我按下tabitem2中节点的按钮,则应该关注tabitem1.如果我关闭

tabItem1并按下相同的Button tabItem1应该再次加载(这发生在

SubGraphButton_Click).

你看到这段代码有问题吗?

  private void ChildNode_Click(object sender, RoutedEventArgs args)
  {
        System.Windows.Controls.Button button = (System.Windows.Controls.Button)sender;
        Node node = Part.FindAncestor<Node>(button);
        MyNodeData nodeData = node.Data as MyNodeData;
        foreach (TabItem item in tabControl.Items)
        {
            if (nodeData.Text == item.Header.ToString())
            {
                item.Focus();
            }
            else if (nodeData.Text != item.Header.ToString())
            {
                SubGraphButton_Click(sender, args);
            }
        }
 }
 private void SubGraphButton_Click(object sender, RoutedEventArgs args)
 {
        string activeDirectory = @"X:\SubGraph\";
        string[] files = Directory.GetFiles(activeDirectory);
        foreach (string fileName in files)
        {
            FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
            System.Windows.Controls.Button button = (System.Windows.Controls.Button)sender;
            Node node = Part.FindAncestor<Node>(button);
            MyNodeData nodeData = node.Data as MyNodeData;
            if (node != null)
            {
                if (nodeData.Text + ".epk" == fileName.Substring(12, fileName.Length - 12) && !tabControl.Items.Contains(tabItem1))
                {
                    tabControl.Items.Add(tabItem1);
                    tabItem1.Focus();
                    var model = new MyGraphLinksModel();
                    model.Modifiable = true;
                    model.HasUndoManager = true;
                    activateDiagram(myDiagram1);
                    activeDiagram.Model = model;
                    model.Name = fileName.Substring(12, fileName.Length - 12);
                    model.Name = model.Name.Substring(0, model.Name.Length - 4);
                    tabItem1.Header = model.Name;
                    activeDiagram.PartManager.UpdatesRouteDataPoints = false;
                    StreamReader reader = new StreamReader(file);
                    string contents = reader.ReadToEnd();
                    XElement root = XElement.Parse(contents);
                    activeDiagram.LayoutCompleted += LoadLinkRoutes;
                    model.Load<MyNodeData, MyLinkData>(root, "MyNodeData",   "MyLinkData");
                }
           }
  }
Run Code Online (Sandbox Code Playgroud)

Ser*_*rvy 7

当修改集合处于修改过程中时,很可能会导致错误.错误的类型及其可能性往往根据底层集合的实际情况而有所不同.修改一个List迭代它很可能会给你很多错误(如果你经常修改它会多关闭一个错误)并且可能会超出边界错误.修改a LinkedList可能会导致空指针异常,无限循环,访问不存在的项等,但可能性要小得多.

因为在一般情况下,问题的可能性相当高,这些问题的影响也相当高,并且难以诊断实际出错的地方(以及在哪里)C#选择在您尝试迭代时抛出异常在迭代期间修改的集合.这样你就不会遇到奇怪的,意想不到的问题,这些问题直到他们根本原因的某个时候才会显现出来.

有几种不同的策略可用于避免此问题:

  1. 迭代与您真正想要修改的集合不同的集合.在某些情况下,这可以简单地通过ToList在序列上添加调用来完成,以便将其移动到新集合中; 在执行此操作时,正在迭代的集合与正在修改的集合是分开的,因此没有错误.

  2. 您可以避免修改foreach循环内部的实际集合.常见的例子是创建一个List或其他集合"修改,使"无论是itemsToAdd,itemsToRemove等等,那么你可以添加/删除/无论对所有的循环后这些项目.(如果您只修改集合大小的一小部分,则此方法很有效.)

  3. 某些类型的集合可以"迭代"而不实际使用传统的迭代器(意味着foreach循环).例如,您可以List使用常规for循环迭代,只需在添加或删除项时修改(递增/递减)循环变量.这一点,如果正确完成,往往是一个有效的选择,但是很容易出错并出错,所以当其他选项(略微)效率较低时,它们是非性能密集型代码的非常好的选择,因为他们的简单.