-2

So, I have a data grid view that needs to be updated in real-time, for a management software. I'm trying to update the control on a separate thread, but it throws an exception:

Cross-thread operation not valid: Control 'dataGridView1' accessed from a thread other than the thread it was created on.

Here is the code:

public void atualiza()
        {
            for (int i = 0; ; i++)
            {
                i--;
                tabela();
                System.Threading.Thread.Sleep(90000);
            }
        }

private void mainUser_Load(object sender, EventArgs e)
    {
        atualizaTabela t = new atualizaTabela(atualiza);
        t.BeginInvoke(null, null);
    }

"Tabela" is the method that actually updates the data grid view:

public void tabela()
        {
            string comando = "SELECT * FROM Job";
            OracleDataAdapter da;
            OracleCommand comm;
            DataSet ds;
            OracleConnection Conn = new OracleConnection(dbstring);
            comm = new OracleCommand(comando, Conn);
            da = new OracleDataAdapter(comm);
            ds = new DataSet();
            da.Fill(ds, "Job");
            dataGridView1.DataSource = ds;
            dataGridView1.DataMember = "Job";
            dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
            dataGridView1.Columns[0].HeaderText = "Id";
            dataGridView1.Columns[1].HeaderText = "Produto";
            dataGridView1.Columns[2].HeaderText = "Cliente";
            dataGridView1.Columns[3].HeaderText = "Data de Pedido";
            dataGridView1.Columns[4].HeaderText = "Previsão de Entrega";
            dataGridView1.Columns[5].HeaderText = "Preço";
            dataGridView1.Columns[6].HeaderText = "Tamanho";
            dataGridView1.Columns[7].HeaderText = "Quantidade";
            dataGridView1.Columns[8].HeaderText = "Comentário";
        }

"Atualizatabela" is a delegate. The exception is thrown when I try to bind the datagridview to the datasource: (dataGridView1.DataSource = ds)

Dannyl
  • 115
  • 2
  • 3
  • 8
  • possible duplicate of [Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on](http://stackoverflow.com/questions/142003/cross-thread-operation-not-valid-control-accessed-from-a-thread-other-than-the) – Parimal Raj Jul 15 '14 at 01:39

2 Answers2

2

As the exception states, you can't access UI elements from a non-UI thread.

I'd suggest using a BackgroundWorker. You can read all about it here.

Here's the basic outline of what you need to accomplish:

  • This appears to be WinForms, so drop a BackgroundWorker onto your Form.
  • Set the WorkerReportsProgress property to True.
  • Subscribe to the DoWork and ProgressChanged events.
  • Get your data from the database, inside the DoWork event, which is on a separate thread.
  • Pass the data to the ProgressChanged event via a call to ReportProgress.
  • Update the grid with the data inside the ProgressChanged event, which occurs on the UI thread, and then you won't get that "cross-thread operation" exception.
Grant Winney
  • 65,241
  • 13
  • 115
  • 165
0

UI controls can generally only be manipulated on the thread that created them. To avoid this error, use the method named Invoke() which can be called from your seperate thread to run your code back on the creating thread for the control. So after your tabela() function has retrieved the data in ds, you could do:

        dataGridView1.Invoke(new Action(() =>
            {
                dataGridView1.DataSource = ds;
                dataGridView1.DataMember = "Job";
                ...
            }));
        };
Burt_Harris
  • 6,415
  • 2
  • 29
  • 64