2012-12-14 44 views
2

我正在努力改進數據庫同步應用程序,該應用程序需要在當時處理數百萬條記錄。我將採用SqlBulkCopy操作,然後在數據庫上使用MERGE將臨時表與當前表合併。但在此之前,我創建了幾個將添加到數據庫中的表。當我使用常規循環時,它工作正常,但是當我創建Parallel.ForEach循環時,它處理大約100條記錄,然後掛起。沒有錯誤,沒有什麼......我認爲它正在達到某種閾值,但不知道如何處理它。當我選擇2個並行線程時,它可以很好地工作,但它會陷入大於2個線程而沒有任何錯誤。使用並行線程時,應用程序卡住

DataTable PRODUCT = new DataTable(); 

ParallelOptions parOptions = new ParallelOptions(); 
parOptions.MaxDegreeOfParallelism = 5; //use max (5) threads that are allowed. 
Parallel.ForEach(dtPs.AsEnumerable(), parOptions, dtPs_row => 
{ 
    try 
    { 
     //some declarations 
     DataRow newProductRow = PRODUCT.NewRow(); 
     newProductRow.SetField("ID", mId); 
     newProductRow.SetField("NAME", name); 
     PRODUCT.Rows.Add(newProductRow); 
    } 
} 
+3

許多線程嘗試同時向「PRODUCT.Rows」添加行。線程安全嗎? –

+0

你有沒有我應該怎麼做的例子? – Andrew

+1

@Andrew你可以在一個鎖定塊中包圍那條線。 – Mir

回答

1

這裏是您的代碼的示例:

DataTable PRODUCT = new DataTable(); 
    Object lockobj = new Object(); 


    ParallelOptions parOptions = new ParallelOptions(); 
    parOptions.MaxDegreeOfParallelism = 5; //use max (5) threads that are allowed. 
    Parallel.ForEach(dtPs.AsEnumerable(), parOptions, dtPs_row => 
    { 
     try 
     { 
      //some declarations 
      lock(lockobj) 
      { 
       DataRow newProductRow = PRODUCT.NewRow(); 
       newProductRow.SetField("ID", mId); 
       newProductRow.SetField("NAME", name); 
       PRODUCT.Rows.Add(newProductRow); 
      } 
     } 
    } 

假設Object lockobj = new Object();是在類級的方法之外。

+1

當我執行'newProductRow.SetField'操作時,是否應該保持'PRODUCT'鎖定狀態?似乎我需要鎖定這個對象,只有當我創建新的行,當我添加行到表? – Andrew

+0

我真的不確定SetField方法是否在父表中做了任何事情,所以我只是封裝了整個事情。 – jmrnet