C# · 12月 28, 2021

c# – Oracle托管驱动程序可以正常使用异步/等待吗?

我正在尝试使用异步/等待.NET功能进行Oracle查询.结果集相当大,大概需要5-10秒才能回来. Window_Loaded挂起了UI线程,本质上我想使用async / wait在后台执行查询,然后用结果更新dataview.

那么这是Oracle驱动程序问题还是代码错误?例如.这里的东西是同步进行的,而不是异步的吗?我使用最新的Oracle.ManagedDataAccess我可以从Oracle的网站获得.

async Task<DataTable> AccessOracleAsync(){ DataTable dt; using(OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings[“connStr”].ConnectionString)) using (OracleCommand cmd = new OracleCommand(@”SELECT * FROM myTbl”,conn)) { await conn.OpenAsync(); using (var reader = await cmd.ExecuteReaderAsync()) { dt = new DataTable(); dt.Load(reader); } } return dt;}private async void Window_Loaded(object sender,RoutedEventArgs e){ await AccessOracleAsync();}

我尝试过这个,但是它仍然是僵局的UI:

async Task<DataView> AccessOracleAsync(){ DataTable dt; using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings[“connStr”].ConnectionString)) using (OracleCommand cmd = new OracleCommand(@”SELECT * FROM myTbl”,conn)) { await conn.OpenAsync().ConfigureAwait(false); using (DbDataReader reader = await cmd.ExecuteReaderAsync().ConfigureAwait(false)) { dt = new DataTable(); await Task.Run(() => dt.Load(reader)).ConfigureAwait(false); } } return dt.AsDataView();}private async void Window_Loaded(object sender,RoutedEventArgs e){ Data1.ItemsSource = await AccessOracleAsync();}

所以最后,我把方法改成了这样的东西,使它不会死锁.看来我有正确的想法,只是Oracle Managed库同步地实现了Async方法(仅符合接口).

private async Task<DataView> AccessOracleAsync(){ DataTable dt = new DataTable(); using (OracleConnection conn = new OracleConnection(ConfigurationManager.ConnectionStrings[“connStr”].ConnectionString)) using (OracleCommand cmd = new OracleCommand(@”SELECT * myTbl”,conn)) { await Task.Run(() => { conn.open(); using (DbDataReader reader = cmd.ExecuteReader()) { dt.Load(reader); } }).ConfigureAwait(false); } return dt.AsDataView();}解决方法 不,被管理的驱动程序不支持异步/等待.

您可以调用这些方法,因为它们必须被实现以符合接口定义,但代码实际上是同步的.你可以使用Task.Run,​​如果你想,但你不能同时有两个电话(Oracle会威胁他们同步).