Updating a DataGrid's content from another thread
I'm trying to update the contents of a DataGrid from another thread. To accomplish this, i'm using a transaction. The scenario is as follows : the user does some input in a textbox on my form, and the DataGrid is updated accordingly. Now, sometimes (it seems that this event occurs randomly), I get the following exception when trying to Commit() the transaction:
"There is already an open DataReader associated with this Connection, which must be closed first."
Maybe opening a new connection each time the user types something and closing it after updating the DataGrid using that connection, and closing it after that will work. However, I doubt that this is the only solution (then, what about server-client apps which may need to open connections for thousands of clients - will they open multiple multiple connections for each client?)
Has anyone encountered this? I'm going to post my code below. Please ignore the comments, they are in romanian and I was too lazy to remove them. The following functions are part of the DataGridUpdate class:
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // rutina de update, care se executa pe alt thread private void WorkerThread() { bRunning = true; // executam tranzactia try { // daca update-ul dispune de rutina de Start, o executam if (bHasRoutines) if (myStartRoutine != null) myStartRoutine(); myDataGrid.BeginInvoke(new DataGridFiller(DataGridUpdater)); myTransaction.Commit(); } // daca a aparut o eroare in urma tranzactiei catch (Exception e) { // incercam sa o anulam try { myTransaction.Rollback(); } // daca nu reusim, semnalam acest lucru catch (MySqlException ex) { MessageBox.Show("A aparut o exceptie de tipul " + ex.GetType() + " cand s-a incercat anularea tranzactiei.\n" + ex.Message + "\n" + ex.Source + "\n" + ex.StackTrace); } // semnalam faptul ca tranzactia nu a putut fi executata MessageBox.Show("A aparut o exceptie de tipul " + e.GetType() + " cand s-a incercat executarea tranzactiei de update\n" + e.Message + "\n" + e.Source + "\n" + e.StackTrace); return; } finally { // daca are rutina de End, o executam if (bHasRoutines) if (myEndRoutine!=null) myEndRoutine(); } bRunning = false; } |
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // rutina publica ce deserveste la update-ul unui datagrid public void Execute() { Stop(); // pornim o noua actualizare a grid-ului myThread = new Thread(new ThreadStart(WorkerThread)); myTransaction = myConnection.BeginTransaction(IsolationLevel.ReadCommitted); myCommand.Transaction = myTransaction; myAdapter.SelectCommand = myCommand; myThread.Start(); |
//-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // rutina publica ce deserveste la oprirea firului de executie suplimentar public void Stop() { if (myThread != null) if (myThread.IsAlive) myThread.Abort(); myThread = null; } |
Each time the user types something, a new object of type DataGridUpdate is created, and then DataGridUpdate.Execute() is called for that object, in order to update the DataGrid on my form.
Has anyone ever tried something similar? If yes, did you encounter the same problem?
Best regards,
Andrei

