MVC-controller kann nicht ausgeführt Async-Methode
Ich habe eine sehr einfache MVC-controller mit one-Aktion:
public class HomeController : Controller
{
public ActionResult Index()
{
OpenConnection().Wait();
return View();
}
private async Task OpenConnection()
{
var synchronizationContext = SynchronizationContext.Current;
Debug.Assert(synchronizationContext != null);
using (
var connection =
new SqlConnection(
@"Data Source=(localdb)\ProjectsV12;Initial Catalog=Database1;Integrated Security=True;"))
{
await connection.OpenAsync(); //this always hangs up
}
}
}
Das problem ist, dass regelmäßige Aktion (nicht async-version) nicht erfüllen können async-Methoden. In meinem Fall OpenConnection () - Methode hängt immer oben an warten auf Verbindung.OpenAsync () - Linie.
Nach einiger Zeit fand ich zwei Wege, um diesen code zu arbeiten.
-
Controller machen action-asynchrone
public async Task<ActionResult> Index() { await OpenConnection(); return View(); }
-
Oder erlauben die asynchrone Ausführung ohne Aufnahme original SychronizationContext für:
await connection.OpenAsync();
ersetzen mit:
await connection.OpenAsync().ConfigureAwait(false);
So, meine Vermutung ist, dass meine anfängliche problem war irgendwo um SynchronizationContext. Aber SynchronizationContext.Strom ist nicht null, und das macht mich Frage mich, ob meine Vermutung richtig ist.
Also, kann jemand erklären, warum nicht async action im MVC-controller kann nicht syncronously ausführen von asynchronen Methoden?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Stephen Cleary hat ein guter blog-post über dieses Thema und es betrifft beide ASP.NET und desktop-apps. Der Grundtenor ist, dass, weil der Kontext (ASP.NET Anforderung Kontext, in deinem Beispiel) wird synchron blockiert durch Ihre ausdrückliche .Wait () - Aufruf, der async-Task kann nicht ausgeführt werden-code über den Kontext zu informieren, dass es beendet wurde, damit es deadlocks.
Er schlägt auch gleich zwei Lösungen, wie Sie (verwenden Sie asynchrone den ganzen Weg hinunter von der top-level-controller-Methode oder ändern Sie Ihre async "Bibliothek" code nicht erfassen-Kontext).