Soudě podle starého kódu (6.7.2) se zdá, že poskytovatel mysql ADO.NET neimplementuje správně žádnou asynchronní funkcionalitu. To zahrnuje vzor TAP a starší asynchronní vzory stylu Begin..., End.... V této verzi se zdá, že asynchronní metody Db* nejsou vůbec zapsány; budou používat ty základní třídy v .NET, které jsou synchronní a všechny vypadají nějak jako:
public virtual Task<int> ExecuteNonQueryAsync(...) {
return Task.FromResult(ExecuteNonQuery(...));
}
(100% synchronní s přidanou režií zabalení do úlohy; referenční zdroj zde )
Pokud by byly verze Begin a End napsány správně (nejsou), mohlo by to být implementováno asi takto:
public override Task<int> ExecuteNonQueryAsync(...) {
return Task<int>.Factory.FromAsync(BeginExecuteNonQueryAsync, EndExecuteNonQueryAsync, null);
}
(referenční zdroj pro tuto metodu pro SqlCommand )
To závisí na nějakém druhu zpětného volání api pro podkladový soket, se kterým se nakonec vypořádá ve vzoru, kdy volající odešle nějaké bajty přes soket a poté se registrovaná metoda zavolá zpět z podkladového síťového zásobníku, když je připravena.
Konektor mysql to však nedělá (nepřepisuje tuto metodu na prvním místě, ale pokud ano, příslušné metody zahájení a ukončení nejsou na některém základním rozhraní socket API asynchronní). Co dělá konektor mysql místo sestaví delegáta pro interní metodu na aktuální instanci připojení a vyvolá ji synchronně v samostatném vláknu. Mezitím nemůžete například provést druhý příkaz na stejném připojení, něco takového:
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;
}
(za předpokladu, že sdružujete připojení a počet úloh je větší než maximální velikost fondu; pokud by asynchronní fungoval, tento kód by získal číslo v závislosti na počtu připojení ve fondu namísto čísla v závislosti na tom i počtu vlákna, která mohou běžet souběžně)
Důvodem je, že kód má zamknout ovladač (skutečná věc, která spravuje vnitřnosti sítě; *). A pokud tomu tak nebylo (a interní prvky byly jinak bezpečné pro vlákna a pro správu fondů připojení byl použit jiný způsob) pokračuje v provádění blokování volání na základním síťovém streamu .
Takže ano, pro tuto kódovou základnu není v dohledu žádná asynchronní podpora. Mohl bych se podívat na novější ovladač, kdyby mě někdo mohl nasměrovat na kód, ale mám podezření na interní NetworkStream
založené objekty nevypadají výrazně odlišně a asynchronní kód také nevypadá příliš odlišně. async
podpůrný ovladač by měl většinu vnitřních součástí zapsána tak, aby závisela na asynchronním způsobu provádění, a měl by synchronní obal pro synchronní kód; alternativně by to vypadalo mnohem více jako SqlClient
referenční zdroj a závisí na nějakém Task
zabalit knihovnu, aby se odstranily rozdíly mezi synchronním nebo asynchronním spuštěním.
* zamykání ovladače neznamená, že by nemohlo používat neblokující IO, jen to, že metoda nemohla být napsána s příkazem lock a použít neblokující Begin/End IAsyncResult
kód, který mohl být napsán před vzory TAP.
Edit:staženo 6.9.8; podle podezření neexistuje žádný funkční asynchronní kód (neblokující IO operace); je zde uložena chyba:https://bugs.mysql.com/bug. php?id=70111
Aktualizace 6. července 2016:zajímavý projekt na GitHubu, který to může konečně vyřešit na https://github.com/ mysql-net/MySqlConnector (pravděpodobně by se dalo použít více přispěvatelů, kteří mají podíl na jeho úspěchu [již na ničem s MySql nepracuji]).