2016-12-14 69 views
1

的我有以下代碼:性能DB異步調用

public static async Task<uint?> GetJobAsync(string name) 
{ 
    return await Program.Database.PerformQueryAsync<uint?>(async (command) => 
    { 
     command.CommandText = "SELECT `job` FROM `people` WHERE `name`[email protected];"; 
     command.Parameters.Add(new MySqlParameter("name", name)); 
     MySqlDataReader reader = await command.ExecuteReaderAsync() as MySqlDataReader; 
     if (!reader.HasRows) 
      return null; 
     reader.Read(); 

     return reader.GetUInt32(0); 
    }); 
} 

public async Task<T> PerformQueryAsync<T>(Func<MySqlCommand, Task<T>> operationAsync) 
{ 
    try 
    { 
     using (MySqlCommand command = CreateCommand()) 
      return await operationAsync(command); 
    } 
    catch (MySqlException ex) 
    { 
     if (ex.GetBaseException() is SocketException) 
     { 
      Console.WriteLine("MySQL connection was broken. Reconnecting..."); 

      if (!IsConnected()) 
       Connect(); 

      using (MySqlCommand command = CreateCommand()) 
       return await operationAsync(command); 
     } 

     throw; 
    } 
} 

第二個函數存在爲標的的MySQL連接經常wait_timeout秒。我的SQL查詢很短,所需時間較短。但是,調用3個異步方法來獲取此信息。這是一個很好的異步用例嗎?我應該轉換爲同步代碼嗎?

我擔心從this微軟的一篇文章顯示了一個簡單的異步調用生成的IL代碼的建議出現。

+0

對於初學者來說,你處理後不重新拋出的catch塊的異常,並重新進行查詢。 –

+0

該函數然後需要返回其他東西;我想讓它不能處理,所以它可能會被進一步捕獲(除非有更好的方法來做這件事,那我就錯過了)。 – Hele

回答

1

答案是它依賴,而且大多在您的上下文。如果這些方法在活動SynchronizationContext的某個環境中運行;例如WinForms,ASP.NET,WPF,那麼你幾乎肯定會喜歡異步,以免阻塞主線程。這在你的情況下尤其重要,因爲你暗示你的數據庫操作經常超時,在此期間主線程會被阻塞。

您鏈接到斯蒂芬Toub的文章是 - 一如既往 - 優秀,他也說 - 尤其是在他的其他文章 - 相對於大多數I/O操作的成本異步開銷完全是微不足道的,特別是網絡調用你的數據庫。

+0

如果網絡調用通過本地主機,這仍然適用嗎? – Hele

+0

@ Hele:是的 - 數據庫(可能)的磁盤I/O和所需的進程間通信仍然遠遠超過任何異步開銷。 – sellotape

0

我想你不應該轉換爲同步代碼 - 因爲異步給你更好的性能。在這種情況下,你的代碼不阻塞 - 那麼系統將使用較少的線程...