SqlDataAdapter.Fill – 异步方法

使用C#/ .NET 3.5。

目前我正在使用SqlDataAdapter.Fill()依次填充2个DataTable。

我希望并行地填充这两个DataTable,同时异步地执行每个DataTable。 但是,没有Fill()方法的异步版本 – 即BeginFill()会很棒!

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

  1. SqlCommand1.BeginExecuteReader //第一个查询,用于DataTable1
  2. SqlCommand2.BeginExecuteReader //第二个查询,用于DataTable2
  3. SqlCommand1.EndExecuteReader
  4. SqlCommand2.EndExecuteReader
  5. DataTable1.Load(DataReader1)
  6. DataTable2.Load(DataReader2)

但是,DataTable.Load()需要很长时间:
执行步骤1到步骤4需要3秒钟。
然后步骤5需要22秒。
第6步需要17秒。
因此,步骤5和6合并39秒。

最终的结果是,这使我没有任何好处而只是一个接一个地做2个SqlDataAdapter.Fills。 我希望最终结果是整个过程只需要最长的查询(或尽可能接近)。

寻找推荐的方法,最终得到一些真正的异步方法来填充DataTable。

或者我自己管理它并滚动2个单独的线程,每个线程填充一个DataTable?

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

List events = new List(); 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()); 

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

以下代码是用记事本编写的,可能甚至没有编译,但希望你能得到这个想法……

 // Setup state as a parameter object containing a table and adapter to use to populate that table here void DoWork() { List 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); }