2

我想知道是否可以通過使用任務異步調用多個具有相同參數的不同存儲過程,然後等待所有結果返回。TPL任務和存儲過程

我有以下幾點:

private Task<DataTable> DataBaseCall(string procedureName, params Pair[] where) 
    { 
     DataTable data = new DataTable(); 
     SqlConnection connection = new SqlConnection(connStr); 

     SqlCommand command = new SqlCommand(procedureName, connection); 
     connection.Open(); 

     for (int i = 0; i < where.Length; i++) 
     { 
      command.Parameters.Add(where[i].First.ToString(), where[i].Second.ToString()); 
     } 

     var readerTask = Task<SqlDataReader>.Factory.FromAsync(command.BeginExecuteReader, command.EndExecuteReader, null); 
     return readerTask.ContinueWith(t => 
      { 
       var reader = t.Result; 
       try 
       { 
        reader.Read(); 
        data.Load(reader); 
        return data; 
       } 
       finally 
       { 
        reader.Dispose(); 
        command.Connection.Close(); 
        command.Connection.Dispose(); 
        command.Dispose(); 
       } 
      }); 
    } 

我與撥打:

private void SetReportVariables(string reportName, string[] storedProcedureName, string _clientGroup, string _clientCode, string _finYear, string _period) 
    { 
     Task[] tasks = new Task[storedProcedureName.Length]; 

     for (int i = 0; i < storedProcedureName.Length; i++) 
     { 
      List<Pair> parameters = new List<Pair>(); 
      parameters.Add(new Pair("@ClientGroup", _clientGroup)); 
      parameters.Add(new Pair("@ClientCode", _clientCode)); 
      parameters.Add(new Pair("@FinYear", _finYear)); 

      tasks[i] = DataBaseCall(storedProcedureName[i], parameters.ToArray()); 
     } 
     Task.WaitAll(tasks); 

     ...........Do something with the DataTables......... 
    } 

我有三個問題。

  1. 任何人都可以告訴我,如果這是一個好辦法嗎?
  2. 任何想法都是爲什麼我的_finYear變量有時會被忽略,這會導致錯誤。
  3. 我可以從任務中返回數據表嗎?

感謝

邁克

回答

0
  1. 沒有什麼根本上的錯誤使用這種方法。
  2. 您不會在代碼中顯示_finYear來自哪裏,但基於您顯示的代碼,我沒有看到任何理由不能正確傳遞到存儲區。
  3. 當然,你可以像這樣返回DataTable。從多個線程併發訪問是不安全的,但它可以跨線程交付沒有問題。

在你的代碼的唯一的小問題是,你應該有另一個try /終於在連續處理邏輯,因爲它可能爲t.Result拋出一個異常,如果有一個與異步調用一個問題Begin/EndExecuteReader這將不要處理命令和連接。所以這會更好:

readerTask.ContinueWith(t =>    
{     
    try 
    { 
     var reader = t.Result;     

     try     
     {      
      reader.Read(); 
      data.Load(reader); 

      return data; 
     } 
     finally 
     {      
      reader.Dispose(); 
     }    
    } 
    finally 
    { 
     command.Connection.Close(); 
     command.Connection.Dispose(); 
     command.Dispose();     
    } 
}); 
+0

嗨感謝您的答覆。我已經添加了如何傳遞上面的變量。我只是傳遞一個存儲的proc名稱數組和三個變量作爲字符串,但由於某種原因,我得到一個System.AggregateException錯誤,存儲過程需要_finYear。奇怪的! – Beats

+0

我可以想出唯一的猜測是你有一個_finYear的空值。如果您在調試器下運行,它應該在發生異常時斷開並且您可以檢查_finYear的值。 –