Съдейки по някакъв стар код (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]).