web-dev-qa-db-ja.com

コントローラーで非同期メソッドを呼び出す

次のようなコントローラーがあります。

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

コントローラーを呼び出すと、次のエラーが表示されます。

現時点では非同期操作を開始できません。非同期操作は、非同期ハンドラーまたはモジュール内で、またはページライフサイクルの特定のイベント中にのみ開始できます。ページの実行中にこの例外が発生した場合、ページに<%@ Page Async="true" %>

今、私はCallSomeMethodWhichDoesAsyncOperationsを制御することはできず、メソッド自体は非同期ではありませんが、内部的に非同期を実行して忘れます。修正するにはどうすればよいですか?コントローラーをAsyncControllerに変更しようとしたか、コントローラーのメソッドを非同期にしようとした。

編集:

AsyncControllerを使用しようとしたときに最初に試したところ、同じ結果が得られました

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

その後

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

これにより、例外が次の「非同期操作がまだ保留中に非同期モジュールまたはハンドラーが完了しました」に変更されました。

22
Christian

現在、CallSomeMethodWhichDoesAsyncOperationsを制御することはできず、メソッド自体は非同期ではありませんが、内部的に非同期の起動と忘れを行います。修正するにはどうすればよいですか?

それを書いた人に連絡して、them修正してください。

真剣に、それが最良の選択肢です。これに対する良い修正はありません-ハックのみです。

次のようにハックすることができます:

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

これは推奨されません。このソリューションは、作業をバックグラウンドスレッドにプッシュするため、async操作が再開されると、HttpContextなどがなくなります。このソリューション実行する処理がまだある間にリクエストを完了します。サーバーが間違ったタイミングで停止/リサイクルされた場合、このソリューションは正しく動作しません。

適切な解決策は1つだけです:change CallSomeMethodWhichDoesAsyncOperations

24
Stephen Cleary