2015-03-12 9 views
14

Próbowałem utworzyć kwerendę Oracle z funkcją async/wait .NET. Zestaw wyników jest dość duży i potrzeba około 5-10 sekund, aby powrócić. Window_Loaded zawiesza wątek interfejsu użytkownika, w zasadzie chciałem użyć async/wait, aby wykonać zapytanie w tle, a następnie zaktualizować widok danych z wynikiem.Czy sterownik zarządzany przez Oracle może korzystać z asynchronizacji/czekać poprawnie?

Czy jest to również problem sterownika Oracle lub błąd kodu? Na przykład. czy coś tu robi się synchronicznie, zamiast asynchronicznie? Używam najnowszego Oracle.ManagedDataAccess, które mogę uzyskać z witryny internetowej 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(); 
} 

Próbowałem to i jest nadal deadlocking 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(); 
} 

Więc w końcu, zmieniłem metodę do czegoś takiego by nie impasu . Wygląda na to, że miałem dobry pomysł, tylko że biblioteka zarządzana przez Oracle zaimplementowała metody Asynchroniczne synchronicznie (tylko po to, aby zachować zgodność z interfejsem).

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

Co można spróbować to wziąć kod dt.Load (czytnik); do zadania takiego jak Task.Run (() => dt.Load (czytnik)); Dalej kod wygląda dobrze dla mnie. –

+1

Do tej pory wysłałem do Oracle e-maila na temat asynchronicznego wsparcia i otrzymałem odpowiedź: "Nie mam żadnych nowych informacji, kiedy spodziewać się asynchronizacji dla ODP.NET, zarządzanego sterownika." – mason

Odpowiedz

10

nr zarządzanego kierowca nie obsługuje async/await.

Można wywoływać te metody, ponieważ muszą być zaimplementowane zgodnie z definicją interfejsu, ale kod jest rzeczywiście synchroniczny. Jeśli chcesz, możesz użyć Task.Run, ale nie możesz mieć dwóch połączeń jednocześnie (Oracle zagrozi je synchronicznym).

+4

Dzięki, gdy próbujemy pobrać 'async' /' czekaj', to bardzo mylące dla niektórych metod oznaczonych 'async' faktycznie zaimplementowanych synchronicznie. – user17753

+0

@ user17753: True. Muszą tam być, aby zachować zgodność z interfejsem. Inaczej nie byłoby ich tam. –

+8

@ user17753 Nie tylko jest mylące, [to frustrujące] (http://stackoverflow.com/questions/28544557/async-io-intensive-code-is-running-slower-than-non-async-why/29034733# 29034733). – mason

6

(Zostawiam to jako odpowiedź, ponieważ wydaje się być „rozwiązanie” coraz Oracle udało kierowcy prawidłowo obsługiwać asynchronicznie.)

znalazłem old thread (od 2010 roku) na stronie Oracle, gdzie Wywiadodawcy Oracle mówią, że nie obsługują tego. Możesz vote (musi mieć konto Oracle), aby ta funkcja została uwzględniona. Po 5 latach niestety zyskuje tylko 60 głosów.

+0

fun fact - 136 głosów – quetzalcoatl

Powiązane problemy