2015-03-12 10 views
14

Ich habe versucht, eine Oracle-Abfrage mit der async/wait .NET-Funktion zu machen. Das Ergebnis ist ziemlich groß und dauert etwa 5-10 Sekunden. Die Window_Loaded hängt den UI-Thread, im Wesentlichen wollte ich async/wait verwenden, um die Abfrage im Hintergrund durchzuführen und dann eine Datenansicht mit dem Ergebnis zu aktualisieren.Kann der Oracle Managed Driver async/korrekt warten?

So ist dies ein Oracle-Treiber-Problem oder ein Codefehler? Z.B. wird hier synchron anstatt asynchron gearbeitet? Ich verwende die neueste Oracle.ManagedDataAccess, die ich von der Oracle-Website bekommen konnte.

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(); 
} 

ich das versucht, und es wird Deadlocks noch die Benutzeroberfläche:

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(); 
} 

Also am Ende, änderte ich die Methode so etwas wie dieses es nicht zu machen Deadlock . Es scheint, dass ich die richtige Idee hatte, nur dass die Oracle Managed Library die Async-Methoden synchron implementiert (nur um der Schnittstelle zu entsprechen).

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(); 
} 
+0

Was könnten Sie versuchen, den Code dt.Load (Leser) zu übernehmen; in eine Aufgabe wie warten Task.Run (() => dt.Load (Leser)); Außerdem sieht der Code gut für mich aus. –

+1

FYI, ich habe Oracle über die Async-Unterstützung gemailt und eine Antwort erhalten: "Ich habe keine neuen Informationen darüber, wann ich Async für ODP.NET, Managed Driver, erwarten kann." – mason

Antwort

10

Nr Der verwaltete Fahrer nicht async/await unterstützt.

Sie können diese Methoden aufrufen, da sie umgesetzt werden müssen, mit der Schnittstellendefinition zu erfüllen, aber der Code ist tatsächlich synchron. Sie können Task.Run verwenden, wenn Sie möchten, aber Sie können nicht zwei Aufrufe gleichzeitig haben (Oracle wird sie synchron bedrohen).

+4

Danke, wenn Sie versuchen, 'async' /' gonna' abzuholen, ist es sehr verwirrend, dass einige Methoden mit der Bezeichnung 'async' tatsächlich synchron implementiert werden. – user17753

+0

@ user17753: Wahr. Sie müssen da sein, um der Schnittstelle zu entsprechen. Sonst wären sie nicht dort gewesen. –

+8

@ user17753 ist es nicht nur verwirrend, [es ist frustrierend] (http://stackoverflow.com/questions/28544557/async-io-intensive-code-is-running-slower-than-non-async-why/29034733# 29034733). – mason

6

(Ich lasse dies als eine Antwort, da sie die „Lösung“ zu bekommen, die Oracle-Treiber zu unterstützen, um richtig async geschaffen zu sein scheinen.)

Ich fand ein old thread (ab 2010) auf dem Oracle-Website, wo Oracle PM sagen, dass sie es nicht unterstützen. Sie können vote (muss ein Oracle-Konto haben), um diese Funktion enthalten zu haben. Nach 5 Jahren sind es leider nur 60 Stimmen.

+0

Spaß Tatsache - 136 Stimmen jetzt – quetzalcoatl