代码之家  ›  专栏  ›  技术社区  ›  AdaTheDev

sqldataadapter.fill-异步方法

  •  8
  • AdaTheDev  · 技术社区  · 15 年前

    使用c/.net 3.5。

    目前,我正在使用sqldataadapter.fill()逐个填充两个数据表。

    我希望通过异步地分别填充这两个数据表,同时并行地填充它们。但是,没有异步版本的fill()方法-即beginfill()会很好!

    我尝试过的一种方法是(伪):

    1. sqlcommand1.beginExecuteReader//第一个查询,用于dataTable1
    2. sqlcommand2.beginExecuteReader//第二个查询,用于dataTable2
    3. sqlcommand1.endExecuteReader
    4. sqlcommand2.endExecuteReader
    5. dataTable1.加载(datareader1)
    6. dataTable2.加载(datareader2)

    但是,dataTable.load()需要很长时间:
    执行步骤1到步骤4需要3秒钟。
    第5步需要22秒。
    第6步需要17秒。
    因此,步骤5和6的组合时间为39秒。

    最终的结果是,这样做并没有给我带来任何好处,只需要做2个sqldataadapter.fills,一个接一个。我希望最终结果是,整个过程只需要最长的查询(或尽可能接近查询的时间)。

    寻找推荐的方法,最终得到真正的异步方法来填充数据表。

    或者我只是自己管理它并滚动两个独立的线程,每个线程填充一个数据表?

    2 回复  |  直到 15 年前
        1
  •  5
  •   James    15 年前

    我建议每个人都有一个单独的工作线程。你可以用 ThreadPool.QueueUserWorkItem .

    List<AutoResetEvent> events = new List<AutoResetEvent>();
    
    AutoResetEvent loadTable1 = new AutoResetEvent(false);
    events.Add(loadTable1);
    ThreadPool.QueueUserWorkItem(delegate 
    { 
         SqlCommand1.BeginExecuteReader;
         SqlCommand1.EndExecuteReader;
         DataTable1.Load(DataReader1);
         loadTable1.Set();
    });
    
    AutoResetEvent loadTable2 = new AutoResetEvent(false);
    events.Add(loadTable2);
    ThreadPool.QueueUserWorkItem(delegate 
    { 
         SqlCommand2.BeginExecuteReader;
         SqlCommand2.EndExecuteReader;
         DataTable2.Load(DataReader2);
         loadTable2.Set();
    });
    
    // wait until both tables have loaded.
    WaitHandle.WaitAll(events.ToArray());
    
        2
  •  1
  •   Neil Barnwell    15 年前

    这是因为 DataTable 有很多要创建的对象(行、值)。您应该在不同的线程中执行适配器和填充数据表,并在继续之前同步等待每个操作完成。

    下面的代码是用记事本编写的,可能还没有编译,但希望你能理解…

    // Setup state as a parameter object containing a table and adapter to use to populate that table here
    
    void DoWork()
    {
        List<AutoResetEvent> signals = GetNumberOfWaitHandles(2);
    
        var params1 = new DataWorkerParameters
            {
                Command = GetCommand1();
                Table = new DataTable();
            }
    
        var params2 = new DataWorkerParameters
            {
                Command = GetCommand2();
                Table = new DataTable();
            }
    
        ThreadPool.QueueUserWorkItem(state => 
            {
                var input = (DataWorkerParameters)state;
                PopulateTable(input);
                input.AutoResetEvent.Set(); // You can use AutoResetEvent.WaitAll() in the caller to wait for all threads to complete
            },
            params1
        );
    
        ThreadPool.QueueUserWorkItem(state => 
            {
                var input = (DataWorkerParameters)state;
                PopulateTable(input);
                input.AutoResetEvent.Set(); // You can use AutoResetEvent.WaitAll() in the caller to wait for all threads to complete
            },
            params2
        );
    
        WaitHandle.WaitAll(signals.ToArray());
    }
    
    
    void PopulateTable(DataWorkerParameters parameters)
    {
        input.Command.ExecuteReader();
        input.Table.Load(input.Command);
    }