32

async/await .NET 機能を使用して Oracle クエリを作成しようとしていました。結果セットは非常に大きく、返されるまでに約 5 ~ 10 秒かかります。Window_LoadedUIスレッドがハングしています。基本的に、非同期/待機を使用してバックグラウンドでクエリを実行し、結果でデータビューを更新したかったのです。

これは Oracle ドライバーの問題ですか、それともコード エラーですか? たとえば、非同期ではなく同期的に行われていることはありますか? Oracle.ManagedDataAccessOracle の Web サイトから入手できる最新のものを使用しています。

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マネージドライブラリが非同期メソッドを同期的に実装したというだけで、私は正しい考えを持っていたようです(インターフェースに準拠するためだけに)。

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

12

(これは、Oracleマネージドドライバーが非同期を適切にサポートするための「解決策」であるように見えるため、回答として残しておきます。)

Oracle のサイトで古いスレッド(2010 年以降)を見つけましたが、Oracle PM はそれをサポートしていないと言っています。その機能を含めるために投票できます(Oracle アカウントが必要です)。5年後、残念ながら60票しか獲得できませんでした。

于 2015-03-13T14:10:22.673 に答える