c# - Dapper QueryAsync 首次阻塞 UI 查询(针对 Oracle 服务器)?

标签 c# asynchronous dapper blocking

首先,我认为第一次只是一个条件,可以更清楚地看到这种阻塞。对于下一次,它仍会以某种方式稍微阻塞 UI,但不像不使用异步时那样明显。

我可以这么说,因为我可以看出使用 QueryAsync 之间的区别和一个简单的包装代码 Task.Run(() => connection.Query<T>)效果很好,当然比 QueryAsync 好得多(在用户体验中)。

代码很简单:

public async Task<IEnumerable<Item>> LoadItemsAsync(){
  using(var con = new OracleConnection(connectionString)){
     var items = await con.QueryAsync<dynamic>("someQuery");
     return items.Select(e => new Item { ... });
  }
}
//in UI thread, load items like this:
var items = await LoadItemsAsync();

工作正常的代码(不阻塞 UI)是这样的:

public async Task<IEnumerable<Item>> LoadItemsAsync(){
  using(var con = new OracleConnection(connectionString)){
     var items = await Task.Run(() => con.Query<dynamic>("someQuery"));
     return items.Select(e => new Item { ... });
  }
}
//in UI thread, load items like this:
var items = await LoadItemsAsync();

我知道Task.Run() 在细节上实际上并不是异步的,但至少它把整个工作放到了另一个线程,使 UI 免于被阻塞和卡住。

我想这可能是 Dapper 中的错误,请花点时间测试一下。我不太确定如何准确重现这个,但如果可能请尝试 Winforms project ,一个相当大的 Oracle 数据库,当然正如我所说,您可以在第一次查询时最明显地看到它(因此请务必在每次测试之前对 Oracle 服务器运行清除缓存查询)。

最后,如果您对此有一些解释和解决方案(当然不使用 Task.Run ),请分享您的答案。

最佳答案

使用 async await,您可以仅在执行真正的异步操作(例如,异步 IO 或委托(delegate)给线程池线程的任务)期间释放和使用 UI 线程。在您的情况下,使用 Oracle 驱动程序 (ODP.NET) 的方法并不是真正的异步。参见 Can the Oracle Managed Driver use async/wait properly?关于 Stack Overflow 的讨论。

如果您想从 UI 线程卸载工作以提高响应速度,只需使用 Task.Run():

var items = await Task.Run(() => LoadItems());

使用任何其他机制,如 Task.ConfigureAwait(false),或同步上下文替换与 Task.Yield() 相结合将导致使用额外的线程池线程也是,但它稍后会释放 UI 线程。

更多信息请查看:

关于c# - Dapper QueryAsync 首次阻塞 UI 查询(针对 Oracle 服务器)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51645396/

相关文章:

Dapper-dot-net "no column name"

c# - 使用 Twitter API 1.1 oAuth 验证和请求用户的时间线

c# - 字符串格式异常

c - Linux,套接字,非阻塞连接

swift - 使用异步方法的 While 循环

dapper - 在 Dapper.net 中使用 'Id' 以外的属性作为主键

c# - 当组(或递归的子组)包含 ForeignSecurityPrincipal 时,GroupPrincipal.GetMembers 失败

c# - 使用 WIF 在 Asp.Net 4.5 上自定义身份验证

javascript - Nodejs 表达从回调到对象的赋值

azure-sql-database - 如何为 Dapper 实现 SQL Azure transient 故障处理框架?