Dapper QueryAsync是否阻止首次查询(针对Oracle服务器)的UI? [英] Dapper QueryAsync blocks UI for the first time querying (against Oracle server)?

查看:0
本文介绍了Dapper QueryAsync是否阻止首次查询(针对Oracle服务器)的UI?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,我认为第一次只是更清楚地看到这种阻塞的一种条件。对于下一次,它仍然以某种方式阻止用户界面轻微,但不像不使用异步时那样明显。

我之所以这样说,是因为我可以看出使用QueryAsync和使用Task.Run(() => connection.Query<T>)的简单包装代码之间的区别。Task.Run(() => connection.Query<T>)工作得很好,当然比QueryAsync(在UX中)要好得多。

代码很简单,如下所示:

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或委托给线程池线程的任务)的过程中释放和使用UI线程。在您的例子中,利用Oracle驱动程序(ODP.NET)的方法并不是真正的异步。参见Can the Oracle Managed Driver use async/wait properly?关于堆栈溢出的讨论。

如果要从UI线程中分流工作以提高响应性,只需使用Task.Run()

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

有关详细信息,请查看:

这篇关于Dapper QueryAsync是否阻止首次查询(针对Oracle服务器)的UI?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆