1

Good morning everyone, I'm having trouble with rewriting a DataGrid, the function works, but I would need to do a faster search, so the thought was to add parallelism.

But upon applying the latter it generates an error for me: System.InvalidOperationException: 'Invalid cross-thread operation: the control 'dataGridView1' was accessed from a different thread than the one from which the creation was performed.'

The problem is clear to me, however I can't figure out how to solve it. Could you guys please help me out?

I've already tried applying Invoke but the program goes into an infinite loop.

private void inputSearch_TextChanged(object sender, EventArgs e)
    {
        Parallel.For(0, 7, i =>
        {
            Ricerca(i);
        });
    }

private void Ricerca(int i)
    {
        string searchValue = inputSearch.Text.ToUpper();
  
        var re = from row in dataTable.AsEnumerable()
                 where
                 row[i].ToString().Contains(searchValue)
                 select row;
        if (re.Count() != 0)
        {
            Invoke(new Action(() =>
            {
                dataGridView1.DataSource = re.CopyToDataTable();
                dataGridView1.Columns[7].Visible = false;
            }));

            
        }
    }
east1000
  • 1,240
  • 1
  • 10
  • 30
Chris
  • 11
  • 1
  • 1
    Don't access the `DataGrid` directly from another thread. Only access your UI from your UI thread. If you have computation that you want to do in parallel, store its result elsewhere and use the UI thread to read those results and apply them to the UI when your worker is done. There are also ways to "delegate" part of the execution into the UI thread but this comes with some caveats, check [`SynchronizationContext`](https://hamidmosalla.com/2018/06/24/what-is-synchronizationcontext/) (more in-depth [here](https://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I)). – CherryDT Oct 04 '21 at 10:20
  • Is the infinite loop anything to do with the first issue? It looks like you fixed one issue using invoke and now you have a second issue. – jdweng Oct 04 '21 at 10:59

2 Answers2

0

You have a deadlock because you are blocking the UI thread in inputSearch_TextChanged method (that is invoked by UI thread).

If your intent is to parallelize the Linq expression, split Ricerca method in two. The final part of the method should be invoked out of the parallel for, maybe directly on inputSearch_TextChanged.

A better solution could be to use .NET Task instead.

Otherwise, if you don't need parallel at all, you can replace it with a simple for.

GibbOne
  • 629
  • 6
  • 10
0

I was able to solve the problem as suggested by Cherry by saving the content in another table and recopying it later.

private void inputSearch_TextChanged(object sender, EventArgs e)
    {
        Parallel.For(0, 7, i =>
        {
            Ricerca(i);
        });
        dataGridView1.DataSource = table;
        dataGridView1.Columns[7].Visible = false;
    }

    private void Ricerca(int i)
    {
        string searchValue = inputSearch.Text.ToUpper();

        var re = from row in dataTable.AsEnumerable()
                 where
                 row[i].ToString().Contains(searchValue)
                 select row;
        if (re.Count() != 0)
        {
            table = re.CopyToDataTable();
        }
    }

Thanks to all!

Chris
  • 11
  • 1