【问题标题】:Asynchronous MVC controller action method execution not waiting at 'await'异步 MVC 控制器操作方法执行不在“等待”处等待
【发布时间】:2014-05-15 04:23:44
【问题描述】:

我正在使用 MVC 4 和 .NET 4.5。我希望利用新的 TAP(异步等待)构建一个异步控制器。我从Controller 而不是AsyncContoller 继承了这个控制器,因为我使用的是基于任务的异步性,而不是基于事件的异步性。

我有两种操作方法 - 一种用于同步执行操作,另一种用于异步执行相同的操作。我的视图中的表单中还有两个提交按钮,每个操作方法一个。

以下是这两种方法的代码:

同步:

[HttpPost]
public ActionResult IndexSync(FormCollection formValues)
{
        int Min = Int32.Parse(formValues["txtMin"]);
        int Count = Int32.Parse(formValues["txtCount"]);
        string Primes;
        DateTime started = DateTime.Now;
        using (BackendServiceReference.ServiceClient service = new ServiceClient())
        {
            Primes = service.GetPrimesServiceMethod(Min, Count);
        }
        DateTime ended = DateTime.Now;
        TimeSpan serviceTime = ended - started;
        ViewBag.ServiceTime = serviceTime;
        ViewBag.Primes = Primes;

        return View("Index");
}

异步:

[HttpPost]
public async Task<ActionResult> IndexAsync(FormCollection formValues)
{
        int Min = Int32.Parse(formValues["txtMin"]);
        int Count = Int32.Parse(formValues["txtCount"]);
        string Primes;
        Task<string> PrimesTask;
        DateTime started = DateTime.Now;
        using (BackendServiceReference.ServiceClient service = new ServiceClient())
        {
            PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count);
        }
        DateTime ended = DateTime.Now;
        TimeSpan serviceTime = ended - started;
        ViewBag.ServiceTime = serviceTime;
        Primes = await PrimesTask;
        ViewBag.Primes = Primes;

        return View("Index");
}

在异步方法中,我希望DateTime ended = DateTime.Now在调用服务方法后立即执行,而耗时的服务方法在后台异步执行。

但是,这不会发生,并且在调用服务方法时执行“等待”,而不是等待Primes = await PrimesTask 发生的位置。

我有什么遗漏的吗?

我们将不胜感激。

【问题讨论】:

  • 您的异步调用是在您调用“Primes = await PrimesTask;”时进行的- 不在使用 AFAIK
  • @MichaelSkarum 使用断点调试,我发现执行“等待”在PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count)。为什么会这样?不应该在Primes = await PrimesTask 等待吗?
  • GetPrimesServiceMethodAsync 里面有什么?你可能在那里阻塞。请注意,await 不会启动新线程(很多人都认为)。
  • @usr 我在 WCF 服务中定义了一个简单的同步方法 GetPrimesServiceMethod(返回 string)。 GetPrimesServiceMethodAsync(返回Task&lt;string&gt;)是WCF在客户端消费生成的代理方法。
  • 那应该没问题。在等待期间暂停调试器。查看调用堆栈(包括外部代码)。这将告诉我们那里正在运行什么并提示为什么

标签: c# .net asp.net-mvc asp.net-mvc-4 asynchronous


【解决方案1】:

我怀疑它实际上阻塞了ServiceClient.Dispose

要解决此问题,请扩展 using 块以包含您的 await

using (BackendServiceReference.ServiceClient service = new ServiceClient())
{
    PrimesTask = service.GetPrimesServiceMethodAsync(Min, Count);
    DateTime ended = DateTime.Now;
    TimeSpan serviceTime = ended - started;
    ViewBag.ServiceTime = serviceTime;
    Primes = await PrimesTask;
}
ViewBag.Primes = Primes;

【讨论】:

  • 我也怀疑这一点 :) 让我想起了您关于 Dispose 与异步工作相结合的文章。
  • 谢谢,@StephenCleary!这解决了我的问题!不过,我很想阅读更多有关它的信息。有链接吗?
  • 我不知道有任何关于这方面的文档。请记住,GetPrimesServiceMethodAsync 在您处置其实例时仍在运行,这不是一个好主意。 :)
  • 回想起来,这似乎是一个愚蠢的错误。无论如何,再次感谢!
猜你喜欢
  • 2023-03-08
  • 1970-01-01
  • 2017-10-08
  • 1970-01-01
  • 1970-01-01
  • 2015-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多