2012-07-19 71 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上的累計時間爲並行讀取多個文件和順序是差不多的)

在任何其他情況下你只有一種方法可以讓你的程序更快(除了獲得更快的服務器,這並不總是可能的):通過減少服務器的工作速度來加快每個請求的速度(使用存儲過程,緩存導致臨時表,減少大型連接...)。