Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# SqlDataAdapter.Fill-异步方法_C#_.net_Asynchronous_Datatable - Fatal编程技术网

C# SqlDataAdapter.Fill-异步方法

C# SqlDataAdapter.Fill-异步方法,c#,.net,asynchronous,datatable,C#,.net,Asynchronous,Datatable,使用C#/.NET 3.5 目前,我正在使用SqlDataAdapter.Fill()逐个填充2个数据表 我想并行地填充这两个数据表,同时异步地填充每一个数据表。但是,Fill()方法没有异步版本,也就是说,beginull()会很棒 我尝试过的一种方法是(伪): SqlCommand1.BeginExecuteReader//1次查询,用于DataTable1 SqlCommand2.BeginExecuteReader//2次查询,用于DataTable2 SqlCommand1.EndEx

使用C#/.NET 3.5

目前,我正在使用SqlDataAdapter.Fill()逐个填充2个数据表

我想并行地填充这两个数据表,同时异步地填充每一个数据表。但是,Fill()方法没有异步版本,也就是说,beginull()会很棒

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

  • SqlCommand1.BeginExecuteReader//1次查询,用于DataTable1
  • SqlCommand2.BeginExecuteReader//2次查询,用于DataTable2
  • SqlCommand1.EndExecuteReader
  • SqlCommand2.EndExecuteReader
  • DataTable1.Load(DataReader1)
  • DataTable2.Load(DataReader2)
  • 但是,DataTable.Load()需要很长时间:
    执行步骤1至步骤4需要3秒钟
    第五步需要22秒
    第六步需要17秒。
    因此,第5步和第6步总共需要39秒

    最终的结果是,与一个接一个地执行2个SqlDataAdapter.Fills相比,这对我没有任何好处。我希望最终结果是整个过程只需要最长查询的时间(或尽可能接近最长查询的时间)

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


    还是我自己管理它,滚动两个单独的线程,每个线程填充一个数据表?

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

    List events=new List();
    AutoResetEvent loadTable1=新的AutoResetEvent(假);
    添加事件(loadTable1);
    ThreadPool.QueueUserWorkItem(委托
    { 
    SqlCommand1.BeginExecuteReader;
    SqlCommand1.EndExecuteReader;
    DataTable1.Load(DataReader1);
    loadTable1.Set();
    });
    AutoResetEvent loadTable2=新的AutoResetEvent(假);
    添加事件(加载表2);
    ThreadPool.QueueUserWorkItem(委托
    { 
    SqlCommand2.BeginExecuteReader;
    SqlCommand2.EndExecuteReader;
    DataTable2.Load(DataReader2);
    loadTable2.Set();
    });
    //等待两个表都加载完毕。
    WaitHandle.WaitAll(events.ToArray());
    
    这是因为
    数据表
    有许多要创建的对象(行、值)。您应该在不同的线程中完成适配器的执行和数据表的填充,并在继续之前同步等待每个操作完成

    下面的代码是用记事本编写的,可能甚至没有编译,但希望您能理解

    // 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);
    }
    
    //将状态设置为参数对象,其中包含用于填充该表的表和适配器
    无效销钉()
    {
    列表信号=GetNumberOfWaitHandles(2);
    var params1=新的DataWorkerParameters
    {
    Command=GetCommand1();
    Table=新数据表();
    }
    var params2=新的DataWorkerParameters
    {
    Command=GetCommand2();
    Table=新数据表();
    }
    ThreadPool.QueueUserWorkItem(状态=>
    {
    变量输入=(DataWorkerParameters)状态;
    可推广(输入);
    input.AutoResetEvent.Set();//可以在调用程序中使用AutoResetEvent.WaitAll()来等待所有线程完成
    },
    参数1
    );
    ThreadPool.QueueUserWorkItem(状态=>
    {
    变量输入=(DataWorkerParameters)状态;
    可推广(输入);
    input.AutoResetEvent.Set();//可以在调用程序中使用AutoResetEvent.WaitAll()来等待所有线程完成
    },
    参数2
    );
    WaitHandle.WaitAll(signals.ToArray());
    }
    void PopulateTable(DataWorkerParameters参数)
    {
    input.Command.ExecuteReader();
    input.Table.Load(input.Command);
    }
    
    一旦我将每一个都排好了队,我怎么能等到两个都完成了呢?我需要填充这两个表,然后才能继续并处理它们。我已将等待概念添加到我的答案中,如果这有帮助的话。@AdaTheDev,您将使用自动重置事件,在工作完成后(在每个单独的线程内)将触发该事件。请参阅@Neils的答案,因为他已经提供了一个示例。我已经更新,向您展示(如果使用我的示例)您将如何实现这一点。谢谢(两者)。我在STA线程上运行,这意味着我不能使用WaitHandle.WaitAll(“不支持STA线程上多个句柄的WaitAll”)。有其他选择吗?谢谢(两个都有)。我在STA线程上运行,这意味着我不能使用WaitHandle.WaitAll(“不支持STA线程上多个句柄的WaitAll”)。是否有其他选择?您可以提供一个
    操作
    回调,该回调仅在调用足够多次后才执行下一位代码?不是很好,但应该有用。为建议和帮助干杯。我做了足够多的工作来做我想做的事情(并行运行这些查询并没有什么真正的好处,因为它们会互相竞争)+我想知道答案,因为它确实有帮助。
    // 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);
    }