I was trying to make an Oracle query with the async/wait .NET feature. The result set is pretty large and takes about 5-10 seconds to come back. The Window_Loaded is hanging the UI thread, essentially I wanted to use async/wait to do the query in the background and then update a dataview with the result.
So is this an Oracle driver issue or a code error? E.g. is something here being done synchronously instead of asynchronously? I'm using the latest Oracle.ManagedDataAccess
I could get from Oracle's web-site.
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();
}
I tried this, and it is still deadlocking the 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();
}
So in the end, I changed the method to something like this to make it not deadlock. It appears I had the right idea, just that the Oracle Managed library implemented the Async methods synchronously (only to comply with the interface).
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();
}
No. The managed driver does not support async
/ await
.
You can call those methods, since they must be implemented to comply with the interface definition, but the code is actually synchronous. You can use Task.Run
if you want to, but you can't have two calls at the same time (Oracle will threat them synchronous).
(I'm leaving this as an answer since it appears to be the "solution" to getting the Oracle managed driver to properly support async.)
I found an old thread (from 2010) on Oracle's site where Oracle PM's say they don't support it. You can vote (must have an Oracle account) to have that feature included. After 5 years it's sadly only gained 60 votes.
来源:https://stackoverflow.com/questions/29016698/can-the-oracle-managed-driver-use-async-wait-properly