Я пытался сделать запрос Oracle с помощью функции async / wait .NET. Набор результатов довольно большой и возврат занимает около 5-10 секунд. Window_Loaded подвешивает поток пользовательского интерфейса, по сути, я хотел использовать async / wait, чтобы выполнить запрос в фоновом режиме, а затем обновить представление данных с результатом.

Так это проблема с драйвером 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();
}
31
user17753 12 Мар 2015 в 20:42

2 ответа

Лучший ответ

Нет. Управляемый драйвер не поддерживает async / await.

Вы можете вызывать эти методы, поскольку они должны быть реализованы в соответствии с определением интерфейса, но на самом деле код является синхронным. Вы можете использовать Task.Run, если хотите, но вы не можете иметь два вызова одновременно (Oracle будет угрожать им синхронно).

23
Patrick Hofman 13 Мар 2015 в 14:05

(Я оставляю это как ответ, поскольку это, по-видимому, «решение» для того, чтобы управляемый драйвер Oracle правильно поддерживал асинхронность.)

Я нашел старую ветку (от 2010 г.) на сайте Oracle, где сотрудники Oracle PM говорят, что не поддерживают Это. Вы можете проголосовать (должна иметь учетную запись Oracle), чтобы включить эту функцию. К сожалению, через 5 лет он получил только 60 голосов.

12
mason 13 Мар 2015 в 14:28