2012-07-19 88 views
0
// 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; 
} 

如果酒吧20项然后简单地使用程序foreach循环花费大约10秒慢 - 执行一个又一个的请求,调用DB每次。多线程是不是程序版本

如果对于相同的数据,使用每个循环的线程,请求需要更长的时间?它看起来像即使线程都很好,向数据库发出的请求 - 从每个线程 - 都在持续着。

如果我修改getData()方法来;所有线程在几乎相同的时间脱火和同时运行4秒钟后退出 -

getData(ref foo){ 

    thread.sleep(4000); 
} 

然后,正如所料,整个请求是在4秒内完成。

我是否缺少与每个线程中数据库调用相关的内容,从而减缓整个过程? - 一些web.config设置并发连接到DB等?

PS。我已经尝试了并行的foreach和Tasks,但它总是返回到数据库调用的线程化,使数据库服务器排队等待所有调用。

+1

您如何知道所有线程都已经完成执行以测量时间?在你已经显示的代码的线程版本中,你只是启动线程,但没有同步点。 – 2012-07-19 09:29:25

+0

0.5s每栏 - 非常慢 - 猜测getData正在做相当数量的SQL - 如果它的线程版本速度较慢,您可能已经有一些死锁正在进行 – BonyT 2012-07-19 09:33:15

+0

我现在有一个基本的监视器(测试时)它在创建每个线程时增加一个线程计数器,并且一旦每个线程调用GetData完成后递减计数器。 – bbose 2012-07-19 09:33:56

回答

0

当线程创建(时间,资源)的成本低于程序执行时间的总结时,多线程会产生效果。

0

并行请求到SQL服务器(或任何其他数据库服务器)将只更快,如果所有的满足下列条件:

  1. 服务器为每个到来的请求的一个空闲的处理器核心(而实际使用每个请求一个线程)
  2. 每个进来的请求涉及到不同的文件(数据库,表...这取决于实际的服务器上)
  3. 每一个批处理文件(每个请求一个)的谎言在它自己的硬盘
  4. 服务器有足够的可用物理内存来同时处理所有请求和所有涉及的数据
  5. 服务器进程不会耗尽内存(不太可能,但在32位系统上,如果您请求大量数据...)

(如果你的服务器有一个SSD,点2和3并不重要 - 在SSD上的累计时间为并行读取多个文件和顺序是差不多的)

在任何其他情况下你只有一种方法可以让你的程序更快(除了获得更快的服务器,这并不总是可能的):通过减少服务器的工作速度来加快每个请求的速度(使用存储过程,缓存导致临时表,减少大型连接...)。