Hop*_*ess 9 c# asynchronous blocking dapper
首先,我认为第一次只是更清楚地看到阻塞的条件.对于下一次,它会以某种方式稍微阻止UI,但不会像不使用异步时那样明显.
我可以这么说,因为我可以看到使用它QueryAsync和一个简单的包装代码之间的区别,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();
Run Code Online (Sandbox Code Playgroud)
代码工作正常(没有阻止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();
Run Code Online (Sandbox Code Playgroud)
我知道Task.Run()实际上并不是对细节的异步,但至少它将整个工作放到另一个线程中,使得UI不会被阻塞和冻结.
我想这可能是一个错误Dapper,请花些时间来测试一下.我不太确定如何完全重现这一点,但是如果可能的话请尝试一个Winforms project相当大的Oracle数据库,当然正如我所说,你可以在第一次查询时看到它最明显(所以一定要运行清算每次测试前针对Oracle服务器的-cache查询).
最后,如果您对此有一些解释和解决方案(当然不使用Task.Run),请分享您的答案.
有了async await你可以免费的,只需一个真正的异步操作的执行过程中使用的UI线程(例如,异步IO或任务委托给一个线程池线程).在您的情况下,使用Oracle驱动程序(ODP.NET)的方法并非真正异步.请参阅Oracle托管驱动程序是否可以正常使用异步/等待?关于Stack Overflow的讨论.
如果您想从UI线程卸载工作以提高响应速度,只需使用Task.Run():
var items = await Task.Run(() => LoadItems());
Run Code Online (Sandbox Code Playgroud)
使用任何其他机制(例如Task.ConfigureAwait(false),或同步上下文替换)Task.Yield()将导致使用额外的线程池线程,但它将在以后释放UI线程.
有关更多信息,请检查