在C#中为多线程锁定数据表的正确方法?

在C#中为多线程锁定数据表的正确方法?,c#,multithreading,datatable,C#,Multithreading,Datatable,这是锁定和修改由多个线程共享的数据表的正确方法吗?如果没有,正确的方法是什么 private void DoGeocodeLookup(object info) { ParameterRow data = (ParameterRow)info; DataRow dr = data.Dr; int localIndex = data.Index; ManualResetEvent doneEvent = data.m_doneEvent; Geocode

这是锁定和修改由多个线程共享的数据表的正确方法吗?如果没有,正确的方法是什么

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(); 
}
我的结构:

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; 
    }
}
启动所有线程的代码段:

//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);
//创建临时表
m_tentable=新数据表();
m_tentable=m_dtAddress.Copy();
对于(int index=0;index
这篇文章内容丰富,可能有助于回答您的问题。一般的共识是使用Interlock.Increment(要更新的对象)。锁定速度很慢,您必须记住可能已锁定正在更新的对象的任何和所有位置。volatile并不一定意味着CPU A会立即看到CPU B的变化

您的示例不需要对
数据表进行任何锁定。在
DoGeocodeLookup
中,您只需读取
数据表
。您对表执行的唯一访问是查找一行,该行被视为读取。该类被标记为对多线程读取操作是安全的。如果要在
DoGeocodeLookup
中添加新行,则需要锁定


您正在更改的唯一内容是由
localIndex
指定的单个
DataRow
中的数据。由于对
DoGeocodeLookup
的每次调用都使用不同的行,因此表中的一行只会由一个线程更新,因此不存在同步问题。因此,这也不需要锁定。

看起来这样可以工作,但为什么不让DataTable变得易变呢?这是更好的方法吗?我想是的。因此,每个线程都将获得最新版本。为什么要使用DataTable创建一个结构,根据C#标准,应该只创建基本类型的结构。结构大小应小于16bytes@Anon-好的。我试试看。如果我声明我的
DataTable
为volatile,那么我不需要包含
lock
语句@印度节目制作人——我认为这是一个很好的观点。我想我不需要将整个
DataRow
传递给线程。我只需要地址组件来构建一个要发送的URL。