[英]ADODB Concurrence issue using task c#
我有一個for循環,在for循環內,我正在調用從SQL Server帶來數據的DB方法。 這很多,大約需要15秒。 我當時在想,也許我可以使用任務來優化它。
問題是當我使用任務時,我等待所有任務。 它給我帶來了與並發有關的問題,有時關閉了閱讀器,還有其他與連接有關的問題。
我從來不需要考慮這種情況,您介意檢查我的ADODB代碼以查看是否有一種方法可以使用該任務而不會出現並發問題嗎?
public IBudget getBudget(int company, string tablename, int year, string account)
{
SqlCommand cmd1;
int x = 1;
if (tablename == "Actual")
x = -1;
Budget item;
item = new Budget();
try
{
cmd1 = new SqlCommand("sp_Dashboard_GetBudget", cnxCRM);
cmd1.CommandType = CommandType.StoredProcedure;
cmd1.Parameters.AddWithValue("@coNum", company);
cmd1.Parameters.AddWithValue("@tablename", tablename);
cmd1.Parameters.AddWithValue("@year", year);
cmd1.Parameters.AddWithValue("@account", account);
if( cnxCRM.State == ConnectionState.Closed)
cnxCRM.Open();
SqlDataReader sqlDataReader = cmd1.ExecuteReader();
if (sqlDataReader.HasRows)
{
while (sqlDataReader.Read())
{
item.GLAccount = sqlDataReader["GLAccountNo"].ToString();
item.Month1 = float.Parse(sqlDataReader["Month1"].ToString()) * x;
item.Month2 = float.Parse(sqlDataReader["Month2"].ToString())* x;
item.Month3 = float.Parse(sqlDataReader["Month3"].ToString())* x;
item.Month4 = float.Parse(sqlDataReader["Month4"].ToString())* x;
item.Month5 = float.Parse(sqlDataReader["Month5"].ToString())* x;
item.Month6 = float.Parse(sqlDataReader["Month6"].ToString())* x;
item.Month7 = float.Parse(sqlDataReader["Month7"].ToString())* x;
item.Month8 = float.Parse(sqlDataReader["Month8"].ToString())* x;
item.Month9 = float.Parse(sqlDataReader["Month9"].ToString()) * x;
item.Month10 = float.Parse(sqlDataReader["Month10"].ToString())* x;
item.Month11 = float.Parse(sqlDataReader["Month11"].ToString())* x;
item.Month12 = float.Parse(sqlDataReader["Month12"].ToString()) * x;
}
}
}
catch (Exception ex)
{
if (cnxCRM.State == ConnectionState.Open)
{
cnxCRM.Close();
throw ex;
}
}
finally
{
//this.cnxCRM.Close();
}
return item;
}
這是我創建任務並等待所有任務的代碼。 函數data.getBudget是給我一些問題的函數:
var getBudgetTask = new List<Task>();
foreach (Checkbook c in list)
{
var getAcc = Task.Run(() =>
{
List<IAccount> accLst = new List<IAccount>();
accLst = data.getAccounts(c.CheckbookID).ToList();
///for each account get the budget
foreach (IAccount acc in accLst)
{
IBudget actual = data.getBudget(c.CompanyNumber, "Actual", DateTime.Now.Year, acc.GLAccount);
IBudget budget = data.getBudget(c.CompanyNumber, "Budget", DateTime.Now.Year, acc.GLAccount);
for (int i = 1; i <= 12; i++)
{
string name = "Month" + i;
final[i - 1].Actual += decimal.Parse(budgetvariable.GetProperty(name).GetValue(actual).ToString());
final[i - 1].Budget += decimal.Parse(budgetvariable.GetProperty(name).GetValue(budget).ToString());
}
}
});
getBudgetTask.Add(getAcc);
}
await Task.WhenAll(getBudgetTask);
謝謝,我將非常感謝您的幫助。
除非啟用了多個活動結果集 (MARS),否則每個連接一次僅允許一個活動SqlDataReader
( 更多信息,請參見此處 )。
因此,您將不得不在每個任務中打開一個新的連接,而不是在各個任務之間共享cnxCRM
。
連接被合並,如果任務數量不是太大(幾十或幾十個但又不是更多),您的方法可能會奏效,那么您就有爭執的風險。
不能保證並行化會解決性能問題,尤其是如果並行化最終以針對相同表的相同執行計划為目標時。
除了@dlatikay的答案外,還要考慮到每個任務有一次數據庫往返,並且正在同一表的數據庫中創建並發。 通過一口氣告訴SQL Server所需的數據並允許SQL Server優化數據檢索策略,您可能會使用較少的計算資源。 這將涉及修改您的sp_Dashboard_GetBudget
一次接受多個公司。
您沒有說明數據庫的大小,但是15秒鍾的時間似乎很長,無法檢索某些帳戶信息。 在SSMS中運行查詢,然后查看查詢計划。 有相當大的機會添加適當的索引將大大加快查詢速度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.