【问题标题】:SqlDataReader OpenAsync hangs applicationSqlDataReader OpenAsync 挂起应用程序
【发布时间】:2014-07-03 18:34:05
【问题描述】:

我正在编写一个简单的类,它将连接到 SQL DB 并从中获取数据。

我想让它异步,但我在异步编程方面遇到了一些问题。

代码:

public async Task<ICommand> ExecuteAsync(SqlConnection connection)
{
    var cmd = new SqlCommand(Query);
    cmd.CommandType = CommandType.Text;
    cmd.Connection = connection;

    if(connection.State != ConnectionState.Open)
        await connection.OpenAsync();

    using (SqlDataReader sqlDataReader = await cmd.ExecuteReaderAsync())
    {
        if (sqlDataReader.HasRows)
        {

            while (await sqlDataReader.ReadAsync())
            {
                Entry = new Entry();
                Entry.ID = (int) sqlDataReader["ID"];
                Entry.User = (string) sqlDataReader["UserName"];
                object o = sqlDataReader["EntryType"];
                Entry.EntryType = o.Equals("Enter") ? EntryType.Enter : EntryType.Leave;
                Entry.DateTime = (DateTime) sqlDataReader["EntryDate"];

            }
        }
    }

使用此代码,调试器总是在 OpenAsync() 方法之后停止执行。它没有命中下一条语句。

你能告诉我我做错了什么吗?

问候

--编辑-- 我现在正在桌面上运行它(简单单元测试) 我添加了 try-catch 来处理异常。

我的最小样本:

ExecuteAsync 方法:

public async Task<ICommand> ExecuteAsync(SqlConnection connection)
{
    var cmd = new SqlCommand(Query);
    cmd.CommandType = CommandType.Text;
    cmd.Connection = connection;

    if(connection.State != ConnectionState.Open)
        await connection.OpenAsync().ConfigureAwait(false);

    using (SqlDataReader sqlDataReader = await cmd.ExecuteReaderAsync().ConfigureAwait(false))
    {
        if (sqlDataReader.HasRows)
        {

            while (await sqlDataReader.ReadAsync().ConfigureAwait(false))
            {
                Entry = new Entry();
                Entry.ID = (int) sqlDataReader["ID"];

// Entry.User = (string) sqlDataReader["UserName"]; // 对象 o = sqlDataReader["EntryType"]; // Entry.EntryType = o.Equals("Enter") ? EntryType.Enter:EntryType.Leave; // Entry.DateTime = (DateTime) sqlDataReader["EntryDate"]; } } } 返回这个; }

调用此方法:

    public void ExecuteCommandAsync(ICommand command, ReadFinished continueWith)
    {
        if(continueWith == null)
            throw new NullReferenceException("Parameter 'continueWith' cannot be null");
        command.ExecuteAsync(_connection).ContinueWith(task => continueWith(task.Result)).ConfigureAwait(false);
    }

我的测试用例:

    public void TestMethod1()
    {
        TimeTableDBConnector.DbConnector connector = new DbConnector(null);
        var getEntryByIDCommand = new GetEntryByIDCommand(1);
        ICommand result;
        try
        {
            connector.ExecuteCommandAsync(getEntryByIDCommand, ContinueWith );
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }


    }

    private void ContinueWith(ICommand command)
    {
        GetEntryCommand cmd = (GetEntryCommand) command;
    }

【问题讨论】:

  • 这个 sn-p 看起来不错。当您使用connection.Open() 而不是connection.OpenAsync() 时,连接是否有效?您是在桌面应用程序还是在服务(或 Web 应用程序)中执行此操作?您能否将其缩减为显示此行为的最小完整示例应用程序?是否有可能抛出异常而您没有正确处理?
  • 用更多代码查看我的编辑。此外,相同的代码,没有异步也能完美运行
  • @Tomasz,删除了我的答案,因为已经发布了更多详细信息。单元测试不使用SynchronizationContext,所以我的回答不适用。
  • 尝试这样称呼它 - command.ExecuteAsync(...).Wait()。您不能在单元测试中触发并忘记异步任务 - 很可能,一旦您退出 TestMethod1,测试就会停止。在获得异步响应之前,您必须在 某处 进行阻塞。
  • 谢谢,等待方法帮助

标签: c# async-await sqldatareader


【解决方案1】:

大多数测试框架都支持异步测试,因此如果您将ExecuteCommandAsync 方法更改为返回Task,您应该能够将您的测试标记为asyncawait 的结果ExecuteCommandAsync。试试这个:

async void TestMethod1()
{
    TimeTableDBConnector.DbConnector connector = new DbConnector(null);
    var getEntryByIDCommand = new GetEntryByIDCommand(1);
    ICommand result;
    try
    {
        await connector.ExecuteCommandAsync(getEntryByIDCommand, ContinueWith );
    }
    catch (Exception e)
    {
        Console.WriteLine(e);
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-07-04
    • 2011-02-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-23
    相关资源
    最近更新 更多