异步odbc似乎是同步的

时间:2017-10-30 08:50:24

标签: c# asynchronous ado.net async-await

我试图进行异步数据库查询,但是当我测试我的代码时,它似乎是同步的。我已将问题隔离到我的查询功能中。无法弄清楚我做错了什么,我对aync / await功能很陌生,所以我可能做了一些愚蠢的事情:)

这是失败的代码:(我使用本地安装的postgresql)

    public static void Main()
    {
        Task.Run(async () => await MainAsync()).GetAwaiter().GetResult();
    }

    public static async Task MainAsync()
    {
        await TestDbSleep(5);
    }

    public static async Task TestDbSleep(int seconds)
    {
        Console.WriteLine("{0} Starting tasks!", DateTime.Now.ToString("HH:mm:ss"));
        var tasks = new[] { DbSleep(5, "first"), DbSleep(seconds, "second"), DbSleep(seconds, "third") };
        Console.WriteLine("All tasks started!");
        await Task.WhenAll(tasks);
        Console.WriteLine("{0} All tasks done!", DateTime.Now.ToString("HH:mm:ss"));
    }

    public static async Task<DbDataReader> DbSleep(int seconds, string name)
    {
        Console.WriteLine("Starting {0}!", name);
        var result = await Query("SELECT * FROM pg_sleep(?)", new OdbcParameter("seconds", seconds));
        Console.WriteLine("{0} done!", name);
        return result;
    }

    public static async Task<DbDataReader> Query(string sql, params OdbcParameter[] parameters)
    {   
        using (var dbConn = new OdbcConnection(ConfigurationManager.ConnectionStrings["MainConnectionString"].ConnectionString))
        {
            await dbConn.OpenAsync();
            var command = new OdbcCommand(sql, dbConn);
            if (parameters != null)
            {
                foreach (var parameter in parameters)
                {
                    command.Parameters.Add(parameter);
                }
            }
            return await command.ExecuteReaderAsync();
        }
    }

当我运行此代码时,我得到了这个输出:

09:29:20 Starting tasks!
Starting first!
first done!
Starting second!
second done!
Starting third!
third done!
All tasks started!
09:29:36 All tasks done!

为什么第二个和第三个任务没有直接启动?为什么需要16秒?

我试图用等待Task.Delay(seconds * 1000)替换对我的Query函数的调用,当我这样做时代码异步执行如下:

09:29:15 Starting tasks!
Starting first!
Starting second!
Starting third!
All tasks started!
third done!
second done!
first done!
09:29:20 All tasks done!

1 个答案:

答案 0 :(得分:3)

问题在于我假设OdbcConnection.OpenAsync()和OdbcCommand.ExecuteReaderAsync()是异步方法,它们不是。

我已经在msdn上读过如何使用SqlConnection和SqlCommand异步,并且我可以将它应用于OdbcConnection / OdbcCommand,结果证明是假的。

我通过使用Npgsql:s NpgsqlConnection,NpgsqlCommand和NpgsqlParameter类而不是.NETs Odbc-classes来实现它。