1

Added this class:

public class MyProgress
        {
            public string Id { get; set; }
            public string Progress { get; set; }
        }

The dowork event:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {            
            BackgroundWorker worker = sender as BackgroundWorker;

            if ((worker.CancellationPending == true))
            {
                e.Cancel = true;
            }
            else
            {
                List<IntPtr> intptrs = GetProcessesIntptrList();
                for (int x = 0; x < intptrs.Count ; x++)
                {
                    GetProcessInfo(intptrs[x]);
                }
                    while (true)
                    {
                        List<MyProgress> prog = new List<MyProgress>();

                        prog = new List<MyProgress>();

                        procList = Process.GetProcesses().ToList();
                        for (int i = 0; i < procList.Count; i++)
                        {
                            Process[] processes = Process.GetProcessesByName(procList[i].ProcessName);
                            PerformanceCounter performanceCounter = new PerformanceCounter();
                            performanceCounter.CategoryName = "Process";
                            performanceCounter.CounterName = "Working Set - Private";//"Working Set";
                            performanceCounter.InstanceName = processes[0].ProcessName;

                            prog.Add(new MyProgress { Id = procList[i].ProcessName, Progress = ((uint)performanceCounter.NextValue() / 1024).ToString("N0") });

                            worker.ReportProgress(0, prog);
                        }
                    }
            }
        }

And last the backgroundworker progresschanged event where I want to add the values of each process to the datagridview1 rows under cell 3.

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            foreach (MyProgress p in (e.UserState as List<MyProgress>))
            {
                currentRow.Cells[3].Value = p.Progress;
                dataGridView1.Rows.Add(
                    p.Progress);
            }
        }

The variable currentRow not exist yet. And I know that cell 3 is where I want to add all the rows of the processes values.

And I also don't know how many rows there should be. And how to do the reporting of each process value to a row under cell 3 ?

I tried this in the progresschanged event:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            foreach (MyProgress p in (e.UserState as List<MyProgress>))
            {
                int rowIdx = dataGridView1.Rows.Add();
                dataGridView1.Rows[rowIdx].Cells[3].Value = p.Progress;
            }
        }

But i'm getting exception on the foreach: The exception is:

Additional information: Collection was modified; enumeration operation may not execute.

System.InvalidOperationException was unhandled by user code
  HResult=-2146233079
  Message=Collection was modified; enumeration operation may not execute.
  Source=mscorlib
  StackTrace:
       at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
       at Automation.Form1.backgroundWorker1_ProgressChanged(Object sender, ProgressChangedEventArgs e) in d:\C-Sharp\Automation\Automation\Automation\Form1.cs:line 719
  InnerException: 
Manuel Spechia
  • 389
  • 1
  • 3
  • 16
  • You should update the GUI from the GUI thread. See http://stackoverflow.com/questions/661561/how-to-update-the-gui-from-another-thread-in-c – Tarik Jul 14 '15 at 02:25
  • 1
    @Tarik `ProgressChanged` event runs on GUI thread – T.S. Jul 14 '15 at 02:31
  • If currentRow does not exist, create a row. I mean, add an if statement to check that the row does not exist and create it. – Tarik Jul 14 '15 at 02:35
  • There are a lot of bugs in this code. The one that makes your program crash right now is the ReportProgress() call, it must be moved outside of the for() loop. You'll now get to deal with the next bug, adding *thousands* of rows a second is not going to work well. Canceling cannot work either. – Hans Passant Jul 14 '15 at 09:10

1 Answers1

1

As far as I understand your question, you need this

Integer rowIdx = dataGridView1.Rows.Add();
dataGridView1.Rows[rowIdx].Cells[3].Value = p.Progress

Why error? - This is because you have design flaw - in backgroundWorker1_DoWork, which runs on background thread, you still modifying collection, which you at the same time passing to progress event. What happens, is while you iterating it on one thread, another thread adds items. What you need to do is make a copy, pass this copy and iterate this copy. Here is one simple way to do it with array

 . . . . 
     MyProgress[] arrP;
     prog.CopyTo(arrP);
     worker.ReportProgress(0, arrP);
 . . . 


private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{

    MyProgress[] progArr  = (MyProgress[])e.UserState;
    foreach (MyProgress p in progArr)
    {
        int rowIdx = dataGridView1.Rows.Add();
            dataGridView1.Rows[rowIdx].Cells[3].Value = p.Progress;
    }
}

I am not sure about this whole design, so I am not trying to change it. Just saying what is wrong now, not in general.

T.S.
  • 18,195
  • 11
  • 58
  • 78
  • T.S i'm getting exception on the foreach in the progresschanged event on the p in the exception: Additional information: Collection was modified; enumeration operation may not execute. – Manuel Spechia Jul 14 '15 at 04:45