Click here to Skip to main content
15,884,983 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
Hello Experts

In my Project, I create many transaction and store them in dataGridView with their details.
When press startbtn this code will execute:
C#
Manager manager = new Manager(GridView);

ANd here is the Manager class:
C#
public class Manager 
{
  public static Dictionary<Thread, int> ThreadList;
  public static DataTable DisposableThreads;

  
  public Manager(DataGridView dgv)
  {
     ThreadList = new Dictionary<Thread, int>();
     DisposableThreads = new DataTable();
     DisposableThreads.Columns.Add(new DataColumn("Thread", typeof(Thread)));

     DisposableThreads.RowChanged += RowChanged;
   
     foreach (DataGridViewRow row in dgv.Rows)
     {
        Thread thread = new Thread(() => Transaction(dgv, (row as GridRow).Row));
   
        ThreadList.Add(thread, (row as GridRow).Row);
        thread.Start();
     }            
  }

  private void RowChanged(object sender, DataRowChangeEventArgs e)
  {
     if (e.Action == DataRowAction.Add)
     {
        ThreadList.Remove((Thread)e.Row.ItemArray[0]);
        DisposableThreads.Rows.Remove(e.Row);
     }
  }

  public void Transaction(DataGridView dataGridView, int row)
  {
     // Some Code
     DisposableThreads.Rows.Add(new object[] { Thread.CurrentThread });
  }
}

Every thing goes fine.
But sometimes when I press stop button to cancel the running threads the below exeception occurs.
Collection was modified; enumeration operation may not execute.

The code in Stop button is:
C#
private void Stop_Click(object sender, EventArgs e)
{
  try
  {
     foreach (Thread t in Manager.ThreadList.Keys)
     {
        if (t.ThreadState == System.Threading.ThreadState.Running)
           t.Abort(); // they really do not abort by this code !!??

     } 
     MessageBox.Show("All operations canceled successfully.");
  }
  catch (Exception ex)
  {
     MessageBox.Show(ex.Message);
  }
}
Posted
Updated 12-Dec-18 18:32pm
v2
Comments
johannesnestler 14-Apr-14 10:03am    
Sounds like a little confusion cause threads are involved etc. But the cause of the error is quite simple. You are changing a collection while you are enumerating it - this is not allowed in C#. Ashok Rathod showed you a way to circumenvent this problem by creating a temp list... I just want to add the answer to your commented question: No, Thread.Abort just throws an exception on the aborted thread, you have to handle the exception in your threads code for yourself. So nothing will be aborted (but it will may fail due unhandled excpetion) if you don't "react" to it in your code. The best advice if in doubt: have a look at MSDN! (Thread.Abort is well documented, as most parts of .NET Framework are)
Meysam Toluie 15-Apr-14 2:55am    
I know the cause of the error is simple. What is not simple is the answer.
johannesnestler 15-Apr-14 7:05am    
Hi Meysam,
Now I had a closer look at Ashoks solution I saw the problem. You have to create an independend(!) collection with the threads to Abort (kind of snapshot at that time). After that try to abort all threads without enumerating the new independend collection (use a for-Loop not foreach).
Meysam Toluie 16-Apr-14 4:53am    
See my solution.

Its seems like in your stop button click you are accessing Manager.ThreadList.Keys
and its static object (it means handled by System) so when you are using dictionary object its modifiable. SO here situation is that one function is continuously modifying that collection and meanwhile stop_Click is using it...
So here you can do one thing ...




C#
private void Stop_Click(object sender, EventArgs e)
{
  try
  {
    Dictionary<thread,> TempThreadList = new Dictionary<thread,>();
    while(Manager.ThreadList.Keys.Count > 0) //will run upto there is any thread is running.
{
  TempThreadList=Manager.ThreadList; //added one more container for continuosly changing collection.

     foreach (Thread t in TempThreadList.Keys)
     {
        if (t.ThreadState == System.Threading.ThreadState.Running)
           t.Abort(); // they really do not abort by this code !!??

     }
}
     MessageBox.Show("All operations canceled successfully.");
  }
  catch (Exception ex)
  {
     MessageBox.Show(ex.Message);
  }
}
 
Share this answer
 
Comments
Meysam Toluie 15-Apr-14 2:53am    
I had tried this one too; The same exception.
I change stop_Click method by this way:
C#
try
{
   while (Manager.ThreadList.Count != 0)
   {
      var t = Manager.ThreadList.FirstOrDefault(x => (x.Key as Thread).IsAlive == true);
                   
      Manager.DisposableThreads.Rows.Add(t.Key);
   }
  
   MessageBox.Show("All operation canceled successfully.");
}
catch (Exception ex)
{
   MessageBox.Show(ex.Message);
}

Also the RowChanged method changes like this:
C#
private void RowChanged(object sender, DataRowChangeEventArgs e)
{
  if (e.Action == DataRowAction.Add)
  {
      if (((Thread)e.Row.ItemArray[0]).IsAlive)
          ((Thread)e.Row.ItemArray[0]).Abort();

      ThreadList.Remove((Thread)e.Row.ItemArray[0]);
      DisposableThreads.Rows.Remove(e.Row);
    }
}
 
Share this answer
 
v3
Comments
johannesnestler 16-Apr-14 6:45am    
nice to hear you solved it - Looks good

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month


CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900