以下启用异步的代码是否容易导致死锁

Is the following async enabled code liable to cause a deadlock

    public async Task<Foo> Execute(int id)
    {
        var parameters = new { id};

        using (var con = new SqlConnection(this.connectionString))
        {
            await con.OpenAsync();

            return await con.QueryAsync<foo>(
                "dbo.uspGetMeFoo",
                parameters,
                commandType: CommandType.StoredProcedure,
                commandTimeout: int.Parse(ConfigurationManager.AppSettings["SqlCommandTimeout"]))
                .ContinueWith(task =>  task.Result.FirstOrDefault());
        }
    }

此方法在调用 class 中等待,其中 - 一段时间后 - 我想在不显式阻塞的情况下使用结果。

我可以通过在调用代码中返回 Task<IEnumerable<Foo>>FirstOrDefault() 来解决这个问题,不使用上面的 ContinueWith

据我所知,上面的阻塞很臭,更糟的是会导致问题,可能是死锁。我对么?

在已经完成的 Task 上调用 Result(您 知道 如果继续触发任务将会完成)不会导致僵局。

当任务需要能够在另一个 thread/context 上安排操作以便能够完成,但 thread/context 阻塞了结果时,就会导致死锁。由于任务已经完成,阻止 thread/context 不可能阻止它完成。

也就是说,您可以轻松 await 任务而不是调用 ContinueWith

正如@Servy所说,你可以很容易地写

public async Task<Foo> Execute(Foo foo )
{
    var parameters = new { id = id};

    using (var con = new SqlConnection(this.connectionString))
    {
        var timeout = int.Parse(
            ConfigurationManager.AppSettings["SqlCommandTimeout"]);

        await con.OpenAsync();

        var query = await con.QueryAsync<Foo>(
            "dbo.uspGetMeFoo",
            parameters,
            commandType: CommandType.StoredProcedure,
            commandTimeout: timeout);

        return query.FirstOrDefault();
    }
}

这不会导致死锁,除非 dbo.uspGetMeFoo 做了一些意想不到的蠢事。这不是问题中代码的问题。