【发布时间】:2015-06-24 10:13:50
【问题描述】:
所以我遇到了一个让我困惑的小问题,我无法找到一个很好的解释 - 我想我可能以某种方式误用了异步/等待功能,但我真的没有不知道我做错了什么。
所以我有一些查询我的数据库并返回单个值的 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
}
}
}
所以在我的代码的其他地方创建了名为 cts 的 CancellationTokenSource,并使用 CancelAfter 方法设置为 2 分钟后过期。
现在我已经使用调试器逐步完成了这段代码,并且我到达了等待调用 ExecuteScalarAsync 的行,没有任何问题。但是,我似乎在执行该行时遇到了两个问题,即它似乎没有返回,2 它忽略了我的取消令牌,并且在我的两分钟取消令牌过期后仍在运行一段时间。
现在我在 Sql Studio 中运行了 sql 查询,它返回的速度非常快——此时该表只有大约 4000 行。
我现在通过将该行更改为:
Int32 oldTransactions = (Int32) command.ExecuteScalar();
几乎立即返回。
这是我更改的唯一代码行,我将其更改回来只是为了确保发生同样的问题。所以我的问题是,异步调用我做错了什么?
【问题讨论】:
-
您是在调用
Task.Wait还是Task<T>.Result进一步调用堆栈?如果是这样,您可能会看到我在博客上解释的deadlock。 -
能否添加显示您如何调用
CheckOldTransactions()以及如何等待它完成的代码? -
嗨,斯蒂芬,是的,在这种情况下,我确实用 .Wait() 调用它 - 我会阅读你的博客,看看是否有帮助。谢谢
-
@StephenCleary 你说过 - 这正是我需要阅读的内容。谢谢
标签: c# sql-server async-await