2015-06-24 131 views
2

所以我遇到了一個令我困惑的小問題,我一直無法找到一個很好的解釋 - 我想我可能會錯誤地使用異步/等待功能不知何故,但我真的不知道我做錯了什麼。ExecuteScalarAsync掛起,但ExecuteScalar立即返回

所以我有一些sql代碼查詢我的數據庫並返回一個單一的值。因此,我使用ExecuteScalarAsync將這個值傳遞給c#。

的代碼如下:

public void CheckOldTransactionsSync() 
{ 
    CheckOldTransactions().Wait(); 
} 

public async Task CheckOldTransactions() 
{ 
    DateTimeOffset beforeThis = DateTime.UtcNow.Subtract(TimeSpan.FromHours(6)); 

    using (SqlConnection connection = new SqlConnection(SqlConnectionString)) 
    { 
     await connection.OpenAsync(cts.Token); 
     using (SqlCommand command = new SqlCommand(@"SELECT TOP 1 1 AS value FROM SyncLog WHERE [TimeStamp] < @BeforeThis;", connection)) 
     { 
      command.Parameters.Add("@BeforeThis", System.Data.SqlDbType.DateTimeOffset, 7); 

      command.Prepare(); 
      command.Parameters["@BeforeThis"].Value = beforeThis; 

      Int32 oldTransactions = (Int32)await command.ExecuteScalarAsync(cts.Token); 

      // do stuff with oldTransactions 
     } 
    } 
} 

所以在我的代碼的其他地方的CancellationTokenSource稱爲CTS創建和設置使用CancelAfter方法2分鐘後到期。

現在我已經通過調試器遍歷了這段代碼,並且到達了等待ExecuteScalarAsync調用沒有問題的那一行。不過,我似乎有兩個問題與執行該行,它似乎並沒有返回,2它忽略了我的取消令牌,並且在我的兩分鐘取消令牌過期後仍然運行一段時間。

現在我已經在Sql Studio中運行了sql查詢,並且它非常快速地返回 - 表格目前只有大約4000行。

Int32 oldTransactions = (Int32) command.ExecuteScalar(); 

幾乎在瞬間返回:

我通過改變線路解決了這個問題現在。

這是我更改的唯一代碼行,我將其更改回來以確保發生相同的問題。所以我的問題是,我對異步調用做了什麼錯誤?

+1

你打電話給'Task.Wait'還是'Task .Result'進一步調用你的調用棧?如果是這樣,你可能會看到我在博客上解釋的[死鎖](http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html)。 –

+0

請問您可以添加顯示您如何調用CheckOldTransactions()的代碼,以及如何等待它的完成? – Nitram

+0

嗨,斯蒂芬,是的,我確實在這種情況下用.Wait()來調用它 - 我會閱讀你的博客,看看它是否有幫助。謝謝 – m3z

回答