Bra*_*don 4 c# task async-await dapper
为什么调用.Result
此方法会导致TaskCanceledException:
public Task<IEnumerable<object>> GetAsync()
{
using (var conn = new SqlConnection("connectionString"))
{
return conn.QueryAsync<object>("select * from objects");
}
}
Run Code Online (Sandbox Code Playgroud)
但是调用.Result
这个方法有效:
public async Task<IEnumerable<object>> GetAsync()
{
using (var conn = new SqlConnection("connectionString"))
{
return await conn.QueryAsync<object>("select * from objects");
}
}
Run Code Online (Sandbox Code Playgroud)
区别在于async\await
第二种方法中使用的是关键字.
The reason the first method throws an exception is because the SqlConnection object is going out of scope when the Task is returned from the method.
The reason the second method works is because the async & await keywords simulate a closure due to the compiler wrapping the method in a state-machine-like struct behind the scenes. This ends up keeping the SqlConnection
in scope. I won't go much further than that because the details are a bit complex and vary based on the compiler.
To make it possible to return a Task without the async/await keywords you'd need to pass in the SqlConnection so it remains in scope upon returning the Task:
public Task<IEnumerable<object>> GetAsync(SqlConnection conn)
{
return conn.QueryAsync<object>("select * from objects");
}
Run Code Online (Sandbox Code Playgroud)
Why it has to do with scope and closures:
SqlConnection
在语句中实例化using
将其范围限制为using
块。因此,当第一个方法离开using
块并返回任务时,任务SqlConnection
就会超出范围并在任务完成之前被释放。在第二种方法中,关键字将导致编译器在后台async/await
创建 a ,并将异步方法的局部变量存储为该结构中的字段,以便在任务完成时可以在回调(await 下面的代码)中使用它们。struct
这类似于闭包在幕后的实现方式。