Mysql
 sql >> база данни >  >> RDS >> Mysql

MySQL C# асинхронните методи не работят?

Съдейки по някакъв стар код (6.7.2), изглежда, че доставчикът на mysql ADO.NET не прилага нито една от асинхронните функции правилно. Това включва шаблона TAP и по-стария стил Начало..., Край... асинхронни модели. В тази версия асинхронните методи Db* изглежда изобщо не са написани; те биха използвали базовите класове в .NET, които са синхронни и всички изглеждат нещо като:

public virtual Task<int> ExecuteNonQueryAsync(...) {
    return Task.FromResult(ExecuteNonQuery(...));
}

(100% синхронно с добавените допълнителни разходи за обвиването му в задача; референтен източник тук )

Ако началната и крайната версии бяха написани правилно (те не са), може да се реализира нещо подобно:

public override Task<int> ExecuteNonQueryAsync(...) {
    return Task<int>.Factory.FromAsync(BeginExecuteNonQueryAsync, EndExecuteNonQueryAsync, null);
}

(референтен източник за този метод за SqlCommand )

Правенето на това зависи от някакъв вид API за обратно извикване за основния сокет, който евентуално да се справи в модел, при който повикващият изпраща някои байтове през сокета и след това регистриран метод се извиква обратно от основния мрежов стек, когато е готов.

Въпреки това, конекторът на mysql не прави това (на първо място не отменя този метод; но ако го направи, съответните начални и крайни методи не са асинхронни на някои основни API на сокет). Какво прави конекторът на mysql вместо това е изграждане на делегат на вътрешен метод на текущия екземпляр на връзката и го извиква синхронно в отделна нишка. Междувременно не можете например да изпълните втора команда на същата връзка, нещо като това:

private static void Main() {
    var sw = new Stopwatch();
    sw.Start();
    Task.WaitAll(
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync(),
        GetDelayCommand().ExecuteNonQueryAsync());
    sw.Stop();
    Console.WriteLine(sw.Elapsed.Seconds);
}

private static DbCommand GetDelayCommand() {
    var connection = new MySqlConnection (...);
    connection.Open();
    var cmd = connection.CreateCommand();
    cmd.CommandText = "SLEEP(5)";
    cmd.CommandType = CommandType.Text;
    return cmd;
}

(ако приемем, че обединявате връзки и броят на задачите там е повече от максималния размер на пула; ако асинхронният пул работи, този код ще получи число в зависимост от броя на връзките в пула, вместо число, зависещо както от това, така и от броя на нишки, които могат да се изпълняват едновременно)

Това е така, защото кодът има заключване на драйвера (действителното нещо, което управлява вътрешните елементи на мрежата; *). И ако не беше (а вътрешните елементи иначе бяха безопасни за нишки и беше използван някакъв друг начин за управление на пулове за връзки) продължава да извършва блокиране на повиквания в основния мрежов поток .

Така че да, не се вижда асинхронна поддръжка за тази кодова база. Бих могъл да погледна по-нов драйвер, ако някой може да ме насочи към кода, но подозирам, че вътрешният NetworkStream базираните обекти не изглеждат значително по-различно и асинхронният код също не изглежда много по-различно. async поддържащият драйвер ще има повечето от вътрешните елементи, написани така, че да зависят от асинхронен начин за извършване и ще има синхронна обвивка за синхронния код; като алтернатива би изглеждал много повече като SqlClient референтен източник и зависят от някаква Task обвиваща библиотека, за да абстрахира разликите между синхронно или асинхронно изпълнение.

* заключването на драйвера не означава, че той не може да използва неблокиращ IO, просто методът не може да бъде написан с оператор за заключване и да използва неблокиращия Begin/End IAsyncResult код, който би могъл да бъде написан преди TAP шаблоните.

Редактиране:изтеглено 6.9.8; както се подозира, няма функциониращ асинхронен код (неблокиращи IO операции); тук има файл за грешка:https://bugs.mysql.com/bug. php?id=70111

Актуализация 6 юли 2016 г.:интересен проект в GitHub, който най-накрая може да реши това на https://github.com/ mysql-net/MySqlConnector (вероятно би могъл да използва повече сътрудници, които имат залог в успеха му [вече не работя по нищо с MySql]).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Laravel:Как да използвате множество релации на централна таблица

  2. Как да зададете набора от символи и съпоставяне на база данни в MySQL

  3. MySQL и NoSQL:Помогнете ми да избера правилния

  4. Как мога да направя три присъединявания към таблицата в заявка UPDATE?

  5. Трудности при инсталиране на mysql gem на Ubuntu