0

Im running a c# code with background worker. Im impelmenting it by having a foreach loop and inside the loop im passing the foreach variable as parameter for the Backgroundworker. But the problem is that whenever i run the code only single random value, most probably the last row in the gridview is passed as parameter. The code is as here

foreach (DataGridViewRow row in dataGridView3.Rows)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.WorkerSupportsCancellation = true;
    worker.DoWork += delegate
    {
        data = dataGridView3.Rows[row.Index].Cells[0].Value.ToString();
        rowindex = row.Index;
        data1 = ros[0].Cells[0].Value.ToString();
    };

    worker.RunWorkerAync();
}
Grant Winney
  • 65,241
  • 13
  • 115
  • 165
  • This is explained at [Eric Lippers blog](http://blogs.msdn.com/b/ericlippert/archive/2009/11/12/closing-over-the-loop-variable-considered-harmful.aspx). – Patrick Jun 15 '13 at 17:22

3 Answers3

2

try by sending parameter as row

worker.DoWork += delegate(object s, DoWorkEventArgs args)
{
    DataGridViewRow  dgr = (DataGridViewRow)args.Argument;
    data = dataGridView3.Rows[dgr.Index].Cells[0].Value.ToString();
    rowindex = dgr.Index;
    data1 = dgr[0].Cells[0].Value.ToString();
};

worker.RunWorkerAsync(row);
Damith
  • 62,401
  • 13
  • 102
  • 153
1

In addition to @Damith's answer, you can also capture the foreach variable in the local scope.

foreach (DataGridViewRow row in dataGridView3.Rows)
{
    DataGridViewRow copy = row; // captured!
    BackgroundWorker worker = new BackgroundWorker();
    worker.WorkerSupportsCancellation = true;
    worker.DoWork += delegate
    {
        data = dataGridView3.Rows[copy.Index].Cells[0].Value.ToString();
        rowindex = copy.Index;
        data1 = copy[0].Cells[0].Value.ToString();
    };

    worker.RunWorkerAync();
}

This is because the row variable is bound to a different value in each iteration, and as such you get the value of row at the last iteration.

This is explained in this answer as well as in Eric Lipperts blog.

Community
  • 1
  • 1
Patrick
  • 17,669
  • 6
  • 70
  • 85
-1

It looks like the line

data = dataGridView3.Rows[row.Index].Cells[0].Value.ToString();

can be modified to:

data = row.Cells[0].Value.ToString();

because it sort of defeats the entire purpose of the foreach statement. Also, the following line seems to have a typo in it:

data1 = ros[0].Cells[0].Value.ToString();

I'm not sure what you intend data1 to contain, but you may want to consider simply passing your BackgroundWorker the DataGridView row variable from your foreach statement, and then pull the necessary data out inside the DoWork method.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Forest Kunecke
  • 2,160
  • 15
  • 32