This list box will contain the name of processes that are currently running. My function to update the list first checks to see if it does not contain the name of a process that is running, then adds the process if it needs to. Then it checks to see if it contains a process that is no longer running, and then it will remove the process.

Here is the code:

private static void UpdateProcessList(ListBox PC_ProcessList)
        {
            while (true)
            {
                if (PC_ProcessList.IsHandleCreated)
                {
                    PC_ProcessList.Invoke(new ThreadStart(
                        delegate
                        {
                            foreach (Process RunningProcess in Process.GetProcesses())
                            {
                                if (!PC_ProcessList.Items.Contains(RunningProcess.ProcessName))
                                {
                                    PC_ProcessList.Items.Add(RunningProcess.ProcessName);
                                }
                            }

                            foreach (object ListedProcess in PC_ProcessList.Items)
                            {
                                if (ReturnProcessInstance(Process.GetProcessesByName(ListedProcess.ToString())) == null)
                                {
                                    try
                                    {
                                        PC_ProcessList.SelectedIndex = PC_ProcessList.SelectedIndex - 1;
                                    }

                                    catch (ArgumentOutOfRangeException)
                                    {
                                        PC_ProcessList.SelectedIndex = PC_ProcessList.SelectedIndex + 1;
                                    }

                                    PC_ProcessList.Items.Remove(ListedProcess);
                                }
                            }
                        }));
                }

                Thread.Sleep(500);
            }
        }

It's throwing an InvalidOperationException when I remove a process from the list. It says "List that this enumerator is bound to has been modified. An enumerator can only be used if the list does not change." And it highlights line 18. Doesn't that mean that the list is modified by something else other than the current foreach block?

I tried to work around it by making two lists of strings and put the names to be added and names to be removed into them, THEN updating the list after both foreach blocks run but it still gave me the InvalidOperationException. I don't think I understand this exception correctly. ;)

Recommended Answers

All 10 Replies

Line 32 is modifying the list which you aren't allowed to do inside of an IEnumerable loop on that list (the foreach is an IEnumerable loop).

Your second method is what you need to do, not sure why you got an error you'll have to post your code.

Your second method is what you need to do, not sure why you got an error you'll have to post your code.

Exactly...that puzzled me too. Here's the code using lists. The last bit is the only time something is added or removed from the list box.

private static void UpdateProcessList(ListBox PC_ProcessList)
        {
            while (true)
            {
                List<string> NamesToAdd = new List<string>();
                List<string> NamesToRemove = new List<string>();

                if (PC_ProcessList.IsHandleCreated)
                {
                    PC_ProcessList.Invoke(new ThreadStart(
                        delegate
                        {
                            foreach (Process RunningProcess in Process.GetProcesses())
                            {
                                if (!PC_ProcessList.Items.Contains(RunningProcess.ProcessName))
                                {
                                    NamesToAdd.Add(RunningProcess.ProcessName);
                                }
                            }

                            foreach (object ListedProcess in PC_ProcessList.Items)
                            {
                                if (ReturnProcessInstance(Process.GetProcessesByName(ListedProcess.ToString())) == null)
                                {
                                    try
                                    {
                                        PC_ProcessList.SelectedIndex = PC_ProcessList.SelectedIndex - 1;
                                    }

                                    catch (ArgumentOutOfRangeException)
                                    {
                                        PC_ProcessList.SelectedIndex = PC_ProcessList.SelectedIndex + 1;
                                    }

                                    NamesToRemove.Add(ListedProcess.ToString());
                                }
                            }

                            foreach (string name in NamesToAdd)
                            {
                                PC_ProcessList.Items.Add(name);
                            }

                            foreach (object name in NamesToRemove)
                            {
                                PC_ProcessList.Items.Remove(name);
                            }

                        }));
                }

                Thread.Sleep(500);
            }
        }

Lists are not threadsafe and you are running this in a loop. This might be causing your problem. Switch to a ConcurrentBag<T> and see if that solves your problem.

Nope...I got the same exception at the same place.

Lock PC_ProcessList at the start of your delegate and unlock it at the end. See what that does (trying to figure out which IEnumerable is breaking :)

Lock it? It doesn't have a method called Lock or Unlock.

lock(PC_ProcessList) {
   foreach ...


}

Ah. Gotcha. Same result. :'( It keeps highlighting the second foreach. ( foreach (object ListedProcess in PC_ProcessList.Items) )

Then I have to say it doesn't like you changing the SelectedIndex. Not sure why that would break the IEnumerable, though, unless any change to the object does that. Odd behavior, IMHO.

Oh wow. Yup, that appears to be it. That is very weird...

Solved. Thank you

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.