【问题标题】:ExecuteScalarAsync hangs but ExecuteScalar returns instantlyExecuteScalarAsync 挂起,但 ExecuteScalar 立即返回
【发布时间】: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&lt;T&gt;.Result 进一步调用堆栈?如果是这样,您可能会看到我在博客上解释的deadlock
  • 能否添加显示您如何调用CheckOldTransactions() 以及如何等待它完成的代码?
  • 嗨,斯蒂芬,是的,在这种情况下,我确实用 .Wait() 调用它 - 我会阅读你的博客,看看是否有帮助。谢谢
  • @StephenCleary 你说过 - 这正是我需要阅读的内容。谢谢

标签: c# sql-server async-await


【解决方案1】:

你打电话给Wait

那是classic ASP.NET deadlock.不要阻塞,或者使用同步IO。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-14
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2018-02-11
    • 2011-10-16
    • 2016-03-10
    • 2014-03-19
    相关资源
    最近更新 更多