Link to home
Start Free TrialLog in
Avatar of l2Bravo
l2BravoFlag for United States of America

asked on

Multithread deadlocking with OleDb.DataTable

I have an application that needs to perform some operations on a separate thread and then write the results of those operations to a database.  The GUI needs to show the contents of the table that contains the results of the worker thread operations in a DataGridView and some associate bound controls.  

Originally, I designed the software so that the worker thread was directly updating the database, i.e., creating an insert command and executing the command, then clearing and fill the datatable with each completed operation.  I decided, though, that such clearing and fill of the datatable wasn't really necessary, so I changed the worker thread so that it creates a new DataRow and adds the datarow to the DataTable displayed on the form that has the DataGridView in the GUI, and simply writes that row to the database without requiring a clear and fill each time a worker thread test finishes.  

An error that cropped up recently, though, is that occasionally when the user switches to the form that has the DataGridView, the programs locks up.  Originally, I thought the error involved some DataGridView DataError, but now I think that my threads must be deadlocking.  I don't know if the change from clearing and refilling the table without adding rows to the table or editing any rows has anything to do with the deadlocking, so any help would be appreciated.  

Thanks.
Avatar of nsanga
nsanga

how do you populate your initial data to the data grid. Is it with datasource property?


if so you better always use data source property binding mechanism of data grid to populate latest data.

Assume your data source name is datasource1. In your worker thread, you can do some thing like this

datasource1.refresh()   and
datagrid1.DataBind()  

so as to get latest data.

Or other option is,

populate the initial data also manually and not by data binding
and add new rows in the worker process.




Avatar of l2Bravo

ASKER

Would accessing the datagridview from a worker thread cause deadlocking because the GUI thread is using that DataGridView?

Also, how would I populate the initial data manually? Just run through each row in the datatable and add it to the datagridview?  
I would channel the datagridview updates through a delegate that is invoked by the parent thread... this would ensure that your threads are not contending with the UI main thread (the parent thread) when the user is interacting with the application.

Example would be to create a method that performs the update then a delegate to match that method and use this.Invoke() to perform the operation of passing from the current thread to the parent thread.
Avatar of l2Bravo

ASKER

can you give me some example code?
       public delegate void performUpdates(DataRow dr);

        private void DoUpdate(DataRow drData)
        {
            //do your dataupdates and refresh your bindings here

        }
        private void callingThread()
        {
            DataRow myData = new DataRow();
            this.Invoke(new performUpdates(DoUpdate), DoUpdate);
        }
err... typo in example make it this:
this.Invoke(new performUpdates(DoUpdate), myData );
Avatar of l2Bravo

ASKER

So, if I understand correctly, I can update the database with an insert command, then create a row and invoke a delegate on the results form that has the DataGridView.  The method that's invoke can then add the rows to the DataTable and thereby update the databindings.  

Would this cause a problem if the thread is run from a class separate from the windows form that has the DataGridView?  All my worker thread operations are performed on 'Manager' classes that manage all the test operations the software needs to perform, but they do have access, if needed to instances of the windows forms used in the application through a separate 'form-holder' class, so I could call the instance of the windows form that has the DataGridView, like so:

FormHolder.Results.Invoke(new performUpdates(DoUpdate), myData)

Is that correct?  
deligate is best one, but the solution i would suggest  is

define these in your background thread

public delegate void performUpdates(DataRow dr);
public performUpdates mobjThreadDeligate;


in your main form ( where datagrid exists ) define a handler as

  private void AddToGrid(DataRow drData)
        {
            //add datarow to grid

        }

also on form load, make sure you have your back ground thread class available

MyThreadClass.mobjThreadDeligate+= new MyThreadClass.performUpdates(me.AddToGrid())


and back to your worker thread, after you update the database, create a datarow (r1) and invoke the deligates as

  foreach (MyThreadClass.performUpdates simpleDelegate1 in mobjThreadDeligate.GetInvocationList)
            {
                simpleDelegate1(datarow)
            }

ASKER CERTIFIED SOLUTION
Avatar of ShazbotOK
ShazbotOK
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial