web-dev-qa-db-fra.com

Appel de la méthode asynchrone dans le contrôleur

J'ai un contrôleur avec quelque chose comme ceci:

public MyController : Controller
{
    public ActionResult DoSomething()
    {
        CallSomeMethodWhichDoesAsyncOperations();
        return Json(new { success = successful }, JsonRequestBehavior.AllowGet);
    }
}

Lorsque j'appelle mon contrôleur, j'obtiens l'erreur suivante:

Une opération asynchrone ne peut pas être démarrée pour le moment. Les opérations asynchrones ne peuvent être démarrées que dans un gestionnaire ou module asynchrone ou pendant certains événements du cycle de vie de la page. Si cette exception s'est produite lors de l'exécution d'une page, assurez-vous que la page est marquée <%@ Page Async="true" %>.

Maintenant, je n'ai pas de contrôle sur CallSomeMethodWhichDoesAsyncOperations et la méthode elle-même n'est pas asynchrone mais fait en interne un certain feu asynchrone et oublie. Que puis-je faire pour le réparer? J'ai essayé de changer le contrôleur en AsyncController et/ou de rendre la méthode dans le contrôleur asynchrone.

Éditer:

Quand j'ai essayé d'utiliser un AsyncController, j'ai essayé pour la première fois, avec le même résultat

public MyController : AsyncController
{
    public ActionResult DoSomething()
    {
        CallSomeMethodWhichDoesAsyncOperations();
        return Json(new { success = successful }, JsonRequestBehavior.AllowGet);
    }
}

Puis

public MyController : AsyncController
{
    public async Task<ActionResult> DoSomething()
    {
        CallSomeMethodWhichDoesAsyncOperations();
        return Json(new { success = successful }, JsonRequestBehavior.AllowGet);
    }
}

Ce qui a changé l'exception en ce qui suit "Un module ou un gestionnaire asynchrone s'est terminé alors qu'une opération asynchrone était toujours en attente."

22
Christian

Maintenant, je n'ai aucun contrôle sur CallSomeMethodWhichDoesAsyncOperations et la méthode elle-même n'est pas asynchrone, mais en interne, elle se déclenche et oublie. Que puis-je faire pour le réparer?

Contactez la personne qui l'a écrit et faites-les le réparer.

Sérieusement, c'est la meilleure option. Il n'y a pas de bonne solution à cela - seulement un hack.

Vous pouvez le pirater pour qu'il fonctionne comme ceci:

public MyController : Controller
{
  public async Task<ActionResult> DoSomething()
  {
    await Task.Run(() => CallSomeMethodWhichDoesAsyncOperations());
    return Json(new { success = successful }, JsonRequestBehavior.AllowGet);
  }
}

Ce n'est pas recommandé. Cette solution pousse le travail vers un thread d'arrière-plan, donc lorsque les opérations async reprendront, elles n'auront pas de HttpContext, etc. Cette solution termine la demande tant qu'il reste du traitement à effectuer. Cette solution ne se comportera pas correctement si le serveur est arrêté/recyclé au mauvais moment.

Il n'y a qu'une seule bonne solution: changer CallSomeMethodWhichDoesAsyncOperations.

24
Stephen Cleary