32

我试图使用 async/await .NET 功能进行 Oracle 查询。结果集非常大,大约需要 5-10 秒才能返回。正在挂起 UI 线程,本质上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 托管库同步实现了 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();
}
4

2 回答 2

24

否。托管驱动程序不支持async/ await

您可以调用这些方法,因为它们必须被实现以符合接口定义,但代码实际上是同步的。您可以根据需要使用Task.Run,但不能同时进行两个调用(Oracle 会威胁它们同步)。

于 2015-03-13T14:05:21.980 回答
12

(我将此作为答案,因为它似乎是让 Oracle 托管驱动程序正确支持异步的“解决方案”。)

我在 Oracle 的网站上发现了一个旧线程(从 2010 年开始),Oracle PM 说他们不支持它。您可以投票(必须拥有 Oracle 帐户)以包含该功能。5年后,遗憾的是它只获得了60票。

于 2015-03-13T14:10:22.673 回答