Ich versuche, meine Basis-Repository-Klasse asynchron zu machen, und ich stehe in Schwierigkeiten. Ich verwende Dapper ORM in meiner C # -Anwendung.
Basismethode
protected async Task<List<T>> Read<T>(CommandDefinition cmd) {
using(SqlConnection myCon = new SqlConnection(Config.DBConnection)) {
await myCon.OpenAsync();
IEnumerable<T> results = await myCon.QueryAsync<T>(cmd);
List<T> retVal = results.ToList();
myCon.Close();
return retVal;
}
}
Methode aufrufen
public List<Category> GetAllActiveCategories(Guid siteGuid) {
return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid).Result;
}
Alles sieht mir in Ordnung. Ich habe die Methodendeklaration mit dem async Schlüsselwort verziert. Ich warte auf asynchrone Methoden.
Das Problem, das ich habe, ist, dass die Thread-Blöcke auf await myCon.OpenAsync();
. Dies ist mein erster Versuch Async zu verwenden und zu warten, also bin ich sicher, dass ich etwas falsch mache, aber es ist nicht offensichtlich. Bitte helfen Sie!
Der geschriebene Lesecode ist in Ordnung. Das Problem liegt im verbrauchenden Code. Es ist üblich , eine Sackgasse mit bekommen async
wenn Sie anrufen Wait()
oder Result
auf der zurückgegebenen Task
oder dessen Vorläufer Task
oben in der Aufrufkette.
Wie immer in diesen Fällen gilt der allgemeine Hinweis: Blockieren Sie den Async-Code nicht . Sobald Sie async/await
, sollten Sie async/await
in der gesamten Aufrufkette verwenden.
So wird deine Aufrufmethode
public Task<List<Category>> GetAllActiveCategoriesAsync(Guid siteGuid) {
return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);
}
... oder
public async Task<List<Category>> GetAllActiveCategoriesAsync(Guid siteGuid) {
List<Category> result = await base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);
// Do something.
return result;
}
Der Schuldige ist:
return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid).Result;
Wie Kirill bemerkt, .Wait()
Sie jedes Mal, wenn Sie .Wait()
oder .Result
für eine Aufgabe verwenden, synchron. Was Sie tun müssen, ist dies:
public Task<List<Category>> GetAllActiveCategories(Guid siteGuid) {
return base.Read<Category>(SPNAME_GETALLACTIVE, siteGuid);
}
Dies wird eine Aufgabe an die aufrufende Methode dieser Methode zurückgeben, und so weiter ... sie muss async "ganz oben" sein.
Wenn der Hauptbenutzer dieses Codes ASP.NET ist, geht es Ihnen gut. Task<IActionResult>
einfach eine Task<IActionResult>
(oder den entsprechenden Rückgabetyp in einer Task) zurück, und das Framework sortiert die für Sie await
Daten aus.
Wenn Sie eine Konsolenanwendung schreiben oder auf andere Weise nicht "async ganz nach oben" machen können, müssen Sie entweder .Result
blockieren oder Ihre Methode async void
und await
. Keiner ist eine großartige Lösung, leider. Async / await ist ziemlich aggressiv in dem Sinne, dass du es wirklich in deinem Stack verwenden musst.