Может ли управляемый драйвер Oracle использовать async/wait правильно?
Я пытался сделать запрос Oracle с функцией async/wait.NET. Результирующий набор довольно большой и занимает около 5-10 секунд, чтобы вернуться. Window_Loaded висит поток пользовательского интерфейса, по сути, я хотел использовать 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();
}
Я пробовал это, и он по-прежнему блокирует пользовательский интерфейс:
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();
}
Ответы
Ответ 1
Нет. Управляемый драйвер не поддерживает async
/await
.
Вы можете вызвать эти методы, так как они должны быть реализованы для соответствия определению интерфейса, но код на самом деле синхронный. Вы можете использовать Task.Run
, если хотите, но у вас не может быть двух вызовов одновременно (Oracle будет угрожать им синхронно).
Ответ 2
(Я оставляю это как ответ, поскольку он, похоже, является "решением" для того, чтобы заставить управляемый драйвер Oracle правильно поддерживать async.)
Я нашел старый поток (с 2010 года) на сайте Oracle, где Oracle PM заявляет, что они его не поддерживают. Вы можете голосовать (должен иметь учетную запись Oracle), чтобы включить эту функцию. Через 5 лет он, к сожалению, только получил 60 голосов.