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

Posted

技术标签:

【中文标题】集合被修改枚举操作可能无法执行【英文标题】:collection was modified enumeration operation may not execute 【发布时间】:2013-09-29 21:30:51 【问题描述】:

好的,如果新表单尚未打开,我想打开它。所以我根据表单的标题或文本检查表单。现在,到目前为止它可以工作,因为表单打开了,如果它已经打开,它只是将它带到前面。但我的问题是,如果它没有打开,并且我尝试创建它的新实例,它会抛出“集合已修改;枚举操作可能无法执行”。而且我终其一生都无法弄清楚为什么。任何帮助表示赞赏。

foreach (DataRow iRow in chatcheck.Rows)

   FormCollection fc = Application.OpenForms;
   foreach (Form f in fc)
   
      if (f.Text != ChatReader["Sender"].ToString())
      

         ChatBox chat = new ChatBox();
         Connection.ConnectionStrings.chatopen = ChatReader["Sender"].ToString();
         chat.Text = Connection.ConnectionStrings.chatopen;
         chat.Show();
         chat.BringToFront();

      
      else if (f.Text == ChatReader["Sender"].ToString())
      
              f.BringToFront();
      
   

【问题讨论】:

【参考方案1】:

不要使用foreach,而是使用for-loop:

for (int i = 0; i < Application.OpenForms.Count; i++ )

    Form f = Application.OpenForms[i];
    if (f.Text != ChatReader["Sender"].ToString())
    

        //...
        chat.Show();
        chat.BringToFront();
    
    // ...

您无法在枚举期间更改 foreach 的基础集合。但是,如果您创建一个新表单并在那里显示它,就会发生这种情况。您将另一个表单添加到打开的集合中。

【讨论】:

谢谢你,它工作得很好......但现在它被封装在foreach(Datarow row in sometable.rows) 中,所以它创造了一个美妙的循环。但我需要那个 Datarow 循环来获取“发件人”信息。所以我不知道如何让它发挥作用。 @Dr_FeelGood:您在循环中根本没有使用iRow。所以我不知道你实际上想要实现什么。也许您需要提出另一个问题,将foreachOpenForms 问题排除在外。 抱歉,它是 iRow 而不是 ChatReader(我忘了切换它,但不管怎样,它仍然会创建一个接近 1200 的循环)。所以它给了我一个相当大的循环而不是打开单个窗口。 感谢@TimSchmelter,这确实解决了我的问题。我试图从(T 的)列表中删除一个项目,但我遇到了另一个问题。 Exit For 一次删除解决了所有问题。希望这也可以帮助某人。 @SikandarAmla:如果你想删除一些东西,请使用向后的for-loop:for (int i = Application.OpenForms.Count-1; i &gt;= 0; i--)... 你也可以使用List.ForEach,它基本上是一个向后for-loop 的包装器和允许修改甚至删除项目。【参考方案2】:

您可以将信息保存在 foreach 循环中(例如,在 List 中),然后使用此信息打开表单。

                var myList = new List<something>();
                foreach (DataRow iRow in chatcheck.Rows)
                
                    FormCollection fc = Application.OpenForms;
                    foreach (Form f in fc)
                    
                        if (f.Text != ChatReader["Sender"].ToString())
                        
                           myList.Add(...)
                        
                        else if (f.Text == ChatReader["Sender"].ToString())
                        
                            f.BringToFront();
                        
                    
                

 

foreach (var val in myList)

   ChatBox chat = new ChatBox();
   ...

【讨论】:

好的,谢谢你们俩。我让它工作。我必须通过formcollection检查表单是否打开,然后通过list.contains()检查它是否在列表中,如果它不是打开的表单或已经在列表中,则将其添加到列表中并打开后来在 Valery Petrov 的解决方案中。非常感谢!【参考方案3】:

为什么在循环和修改Dictionary 时不使用foraeach? 我们可以使用foreach 遍历字典,其键如下:

            //get key collection from dictionary into a list to loop through    
            List<int> keys = new List<int>(Dictionary.Keys);

            // iterating key collection using simple for-each loop
            foreach (int key in keys)
             
                // Now we can perform any modification with values of dictionary.    
                Dictionary[key] = Dictionary[key] - 1; 

            

这是一篇关于它的帖子:How To Iterate a Dictionary Using Keys In C#

【讨论】:

【参考方案4】:

真实代码位于WinForms 应用程序的MainForm 内。

    /// <summary>
    /// Creates and connects the hub connection and hub proxy. 
    /// </summary>
    private async void ConnectWithRetryAsync()
    
        Connection = new HubConnection(Properties.Settings.Default.ServerBaseUrl);
        Connection.Closed += Connection_Closed;
        Connection.Error += Connection_Error;
        HubProxy = Connection.CreateHubProxy("signalcalendar");

        //Handle incoming event from server: use Invoke to write to log from SignalR's thread
        HubProxy.On<CalendarUpdateRequest>("UpdateCalendarEvent", (calendarUpdateRequest) =>
            this.Invoke((Action)(() =>
            
                try
                
                    if (calendarUpdateRequest == null) return;

                    // Reject my own calendar's changes
                    if (calendarUpdateRequest.UserInfo.UserId == Program.UserInfo.UserId) return;

                    //Notify all opened Form about Calendar changes
                    for (int i = 0; i < Application.OpenForms.Count; i++)
                    
                        var openForm = Application.OpenForms[i];

                        try
                        
                            var currentFormType = openForm.GetType();
                            if (currentFormType == typeof(CommonForm))
                            
                                if ((openForm as CommonForm).AppWindowType == AppWindowTypes.FactTruckForm ||
                                    (openForm as CommonForm).AppWindowType == AppWindowTypes.PlanTruckForm ||
                                    (openForm as CommonForm).AppWindowType == AppWindowTypes.FactExcForm ||
                                    (openForm as CommonForm).AppWindowType == AppWindowTypes.PlanExcForm)
                                
                                    (openForm as CommonForm).CalendarHasBeenChanged(calendarUpdateRequest);
                                
                            
                        
                        catch (Exception ex)
                        
                            logger.Error(ex);
                        
                    
                
                catch (Exception ex)
                
                    logger.Error(ex);
                
            
            ))
        );

        #region  Connect to the Server
        try
        
            await Connection.Start();
        
        catch (HttpRequestException ex)
        
            var errorMessage = "There is no connection with Server. Check your netwrok and Server App state";
            logger.Error(errorMessage);
            logger.Error(ex);

            MetroMessageBox.Show(this, errorMessage, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);

            Close();
        

        #endregion

        //Activate UI          
        logger.Info("COnnection has been established OK");
    

【讨论】:

以上是关于集合被修改枚举操作可能无法执行的主要内容,如果未能解决你的问题,请参考以下文章

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

C# 集合已修改;可能无法执行枚举操作

System.invalidoperationexception:集合被修改;枚举操作可能无法在 .net 5 api 项目中执行

修改了实体框架集合;枚举操作可能无法执行

C# - 集合已修改;枚举操作可能无法执行

集合已修改;可能无法执行枚举操作。