C# 方法调用的多线程(从SQL Server检索数据)比过程版本慢

C# 方法调用的多线程(从SQL Server检索数据)比过程版本慢,c#,asp.net-mvc,.net-4.0,C#,Asp.net Mvc,.net 4.0,如果bar有20个项目,那么简单地使用过程性foreach循环大约需要10秒——执行一个又一个请求,每次调用DB 如果,对于相同的数据,每个循环使用线程,那么请求需要更长的时间?!看起来,即使所有线程都很好,但来自每个线程的对DB的请求仍在拖延时间 如果我将getData()方法修改为 // procedural foreach (var foo in bar) { foo.someProperty = getData(

如果bar有20个项目,那么简单地使用过程性foreach循环大约需要10秒——执行一个又一个请求,每次调用DB

如果,对于相同的数据,每个循环使用线程,那么请求需要更长的时间?!看起来,即使所有线程都很好,但来自每个线程的对DB的请求仍在拖延时间

如果我将getData()方法修改为

// procedural 
foreach (var foo in bar)
{                                 
    foo.someProperty = getData(ref foo);     
}

// threaded
foreach (var foo in bar)
{                                         
    ThreadStart work = delegate
    {
        getData(ref foo);
    };

   new Thread(work).Start();    
}

getData(ref foo){

    // Either  a LINQ query 

    // Or Exec Command to Stored procedure in SQL Server

    // Either taking approx 2 seconds to return results

    foo.someProperty = resultsFromDBOrLinqStatement;
}
然后,正如预期的那样,整个请求在4秒钟内完成——所有线程几乎同时启动,并在4秒钟后并发运行并退出

每个线程中的DB调用是否遗漏了一些东西,从而使整个过程变慢了是否为数据库等的并发连接设置了一些web.config


另外,我已经尝试过并行foreach和Tasks,但它总是返回到线程化,数据库调用会减慢速度,就好像数据库服务器正在排队等待所有调用一样。

当线程创建成本(时间、资源)增加时,多线程会产生效果小于过程执行时间的摘要。

只有在满足以下所有条件时,对SQL server(或任何其他数据库服务器)的并行请求才会更快:

  • 对于每个传入请求,服务器都有一个空闲处理器内核(实际上每个请求使用一个线程)
  • 每个传入请求涉及不同的文件(数据库、表…取决于实际服务器)
  • 每批文件(每个请求一个)都位于自己的硬盘上
  • 服务器有足够的可用物理内存,可以同时处理所有请求和所有相关数据
  • 服务器进程不会耗尽内存(不太可能,但在32位系统上,如果您请求大量数据…)
  • (如果您的服务器有SSD,第2点和第3点无关紧要-在SSD上,并行和顺序读取多个文件的累计时间大致相同)


    在任何其他情况下,只有一种方法可以使程序更快(除了获得更快的服务器,这并不总是可能的):通过减少服务器的工作量(使用存储过程、将结果缓存在临时表中、减少大型连接等)使每个请求本身更快.

    为了测量时间,您如何知道所有线程都已完成执行?在您所展示的代码的线程版本中,您只启动线程,但没有同步点。每小节0.5秒-相当慢-猜测getData正在执行相当多的SQL-如果线程版本中的速度较慢,您可能会遇到一些死锁,而我现在有一个基本的监视器(测试时)在创建每个线程时递增线程计数器,在每个线程调用GetData完成后递减计数器。
    getData(ref foo){
    
        thread.sleep(4000);
    }