3

Okay, so I want to open a new form if it isn't already open. So I check for the form based on the Title or text of the form. Now, so far it works, as in the form opens and if it is already open, it just brings it to the front. But my problem being, that if it isn't open, and I try to create a new instance of it, it throws me the "Collection was modified; Enumeration operation may not execute". And I cannot for the life of me figure out why. Any help is appreciated.

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();
      }
   }
}
Adam
  • 2,422
  • 18
  • 29
Dr Archer
  • 348
  • 1
  • 3
  • 14

4 Answers4

7

Don't use a foreach but a 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();
    }
    // ...
}

You canot change the underlying collection of a foreach during enumeration. But that happens if you create a new form and show it there. You add another form to the open-collection.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • Thank you, that worked perfectly... but that's now encased inside a `foreach(Datarow row in sometable.rows)` so it's creating a wonderful loop. But I need that Datarow loop to get the "Sender" info. So i'm stuck as to how to get this to work. – Dr Archer Sep 29 '13 at 22:14
  • @Dr_FeelGood: You are not using `iRow` at all in the loop. So i don't know what you're actually trying to achieve. Maybe you need to ask another question leaving the `foreach` and `OpenForms` issue out. – Tim Schmelter Sep 29 '13 at 22:20
  • Sorry it was meant to be the iRow instead of ChatReader (I forgot to switch it, but either way it's still creating a loop of near 1200). So it's giving me a rather large loop instead of opening the single window. – Dr Archer Sep 29 '13 at 22:33
  • Thanks @TimSchmelter, that indeed solved my problem. I was trying to remove an item from the list(of T) and I got into an another problem. Exit For once removed solved all the problems. Hope this too can help someone. – Sikandar Amla Dec 02 '14 at 11:50
  • @SikandarAmla: if you want to remove something use a backwards `for`-loop: `for (int i = Application.OpenForms.Count-1; i >= 0; i--)...` You can also use [`List.ForEach`](http://msdn.microsoft.com/en-us/library/bwabdf9z%28v=vs.110%29.aspx) which is basically a wrapper for a backwards `for`-loop and allows to modify or even remove the item. – Tim Schmelter Dec 02 '14 at 12:09
1

You can save the information in a foreach loop (e.g. in a List<>), and then open the form, using this information.

                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();
   ...
}
Valery Petrov
  • 653
  • 7
  • 19
  • Okay thank you both of you. I got it to work. I had to check if the form was open via the formcollection, and then check if it was in the list via `list.contains()` and if it wasn't an open form or already in the list, then it was added to list, and opened later in Valery Petrov's solution. Much thanks! – Dr Archer Sep 29 '13 at 22:56
0

Why not to use a foraeach when looping through and modifying a Dictionary?? We can loop through a dictionary using foreach with its keys as below:

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

            }

Here is a Post about it : How To Iterate a Dictionary Using Keys In C#

Language Lassi
  • 2,520
  • 21
  • 24
0

Real life code is inside of the MainForm of WinForms app.

    /// <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");
    }
NoWar
  • 36,338
  • 80
  • 323
  • 498