Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Correct way to lock a DataTable in C# for multithreading?

Is this the correct way to lock and modify a DataTable that is shared by multiple threads? If not, what would be the correct way to do it?

private void DoGeocodeLookup(object info)
{
    ParameterRow data = (ParameterRow)info;
    DataRow dr = data.Dr;
    int localIndex = data.Index;
    ManualResetEvent doneEvent = data.m_doneEvent; 

    Geocode_Google.GeoCode gc = new GeoCode();

    gc.Addr_In = m_dtAddress.Rows[localIndex]["AddressStd_tx"].ToString();

    gc.GeoCodeOne();

    if (gc.Status == "OK")
    {
        //write back to temporary datatable
        lock( m_TempTable.Rows.SyncRoot )
        {
            m_TempTable.Rows[localIndex]["GL_Address"] = gc.Thoroughfare_tx; 
        }
    }
    doneEvent.Set(); 
}

My Structure:

struct ParameterRow
{
    private DataRow m_row;
    private int m_index;

    public DataRow Dr
    {
        get { return m_row; }
        set { m_row = value; }
    }

    public int Index
    {
        get { return m_index; }
        set { m_index = value; }
    }

    public ManualResetEvent m_doneEvent;

    public ParameterRow( DataRow row, int index, ManualResetEvent doneEvent)
    {
        m_row = row;
        m_index = index;
        m_doneEvent = doneEvent; 
    }
}

Snippet where I start all threads:

//make temporary table
m_TempTable = new DataTable();
m_TempTable = m_dtAddress.Copy();

for (int index = 0; index < m_geocodes; index++)
{
    doneEvents[index] = new ManualResetEvent(false);
    ThreadPool.QueueUserWorkItem(DoGeocodeLookup, new ParameterRow( m_dtAddress.Rows[index], index, doneEvents[index]));  
}

WaitHandle.WaitAll(doneEvents);
like image 747
Cuthbert Avatar asked Jan 07 '13 18:01

Cuthbert


1 Answers

Your example does not require any locking of the DataTable. Inside of DoGeocodeLookup you are only peforming reads of the DataTable. The only access you are performing on the table is to look up a row, which counts as a read. The DataTable class is marked as being safe for multi-threaded read operations. If you where doing something like adding new rows in DoGeocodeLookup then you would require locking.

The only thing that you are changing is the data in a single DataRow specified by localIndex. Since each call to DoGeocodeLookup uses a differnet row - a single row in your table will only ever be updated by one thread, so you do not have a synchronization issue there. So that will require no locking either.

like image 130
shf301 Avatar answered Nov 14 '22 22:11

shf301