【问题标题】:Async is not working in large ASP.NET Application but in new application异步不适用于大型 ASP.NET 应用程序,但在新应用程序中
【发布时间】:2016-01-20 00:05:02
【问题描述】:

我有一个现有的大型 ASP.NET(ASP.NET Web 窗体 + MVC 支持)应用程序并尝试在项目上实现 async 编程。

为此,我通过选择 ASP.NET 应用程序(再次支持 ASP.NET Web 窗体 + MVC)创建了一个全新的 POC。我的 POC 运行良好,可以正确执行 async

现在,当我在现有大型项目中复制完全相同的代码时,其行为类似于 synchronous。我已经在大型应用程序中获得了最新的 .NET Framework 更新。 这是我的Controller 实现,它应该上传文件async

[HttpPost]
[ValidateInput(false)]
public async Task<JsonResult> VideoUpload(string Id)
{
    for (int i = 0; i < Request.Files.Count; i++)
    {
        // :::::
        await Run(fileStream);
    }

    return Json(new { error = false, message = "File uploaded." });
}

public async Task Run(Stream fileStream)
{
    // :::::

    using (fileStream)
    {
        // A long running method call
        await fileUploadRequest.UploadAsync();
    }
}

[HttpGet]
public JsonResult GetUploadingStatus()
{
    // :::::
    return Json(new { statusMessage = statusMessage, totalSent = totalSent, totalSize = totalSize }, JsonRequestBehavior.AllowGet);
}

在上面的代码中GetUploadingStatus() 是一个GET 方法可以快速完成工作。此方法接收随机(3-4 秒间隔)Ajax 调用并返回上传状态。

当我在大型项目中调试此实现时,我注意到 GetUploadingStatus()fileUploadRequest.UploadAsync() 结束后一次返回每个结果(10-15 Json 响应)。所以我觉得这在大型项目中表现得像synchronous。那么为什么这在干净的项目中效果很好,但在大型项目中却不行呢?

【问题讨论】:

  • 你的实际项目和POC配置是一样的吗?包括环境配置、web配置、会话等?
  • 我认为您错误地将“异步编程”与“并行编程”混为一谈。异步的要点是将等待线程释放到线程池,而异步 I/O 操作等待结果。异步不会提高单个请求的应用程序性能,但它可以允许同时处理更多请求
  • 谢谢南迪普。即使在实际项目中,我的实现也非常干净。我只想启用异步行为,我认为环境配置或 web.config 或会话不会发挥任何作用。即使我看不到任何错误。
  • Alex Art: async 是将等待线程释放到线程池,而异步 I/O 操作等待结果?异步和异步有什么区别?
  • 你的逻辑毫无意义。 Ajax 调用是单独的 http 请求。他们与之前或之后的任何其他呼叫都没有关系。因此,异步或同步在这方面毫无意义,因为它们实际上是不同的请求。我会看看你如何锁定你用来在请求之间通信/存储进度的任何东西。

标签: c# asp.net asp.net-mvc asynchronous async-await


【解决方案1】:

据我了解,您正在发出并行请求:1 个请求正在上传文件,同时您向 GetUploadingStatus 发出请求以获取上传进度。

在这种情况下,ASP.NET 会话状态的工作方式可能会导致您提到的行为。正如这个答案中提到的Why would multiple simultaneous AJAX calls to the same ASP.NET MVC action cause the browser to block? 2nd request 仅在 first 执行后执行。您所遇到的情况与您提到的相同“..GetUploadingStatus() 在 fileUploadRequest.UploadAsync() 结束后一次返回每个结果(10-15 Json 响应)......”

除了 Alex 提到的之外,您错误地将“异步编程”与“并行编程”混合在一起,即在这种情况下是并行请求..

【讨论】:

  • 嗯,有道理。我认为禁用会话行为会起作用,比如用 [SessionState(SessionStateBehavior.Disabled)] 装饰控制器。
  • 似乎 [SessionState(SessionStateBehavior.Disabled)] 正在工作,将在测试后尽快更新答案。
  • 很高兴知道它有助于解决...总之,ASP.NET 会话状态在这种情况下可能会导致问题,无论是 Web 表单、MVC,我们需要相应地克服它.. plz用详细的解决方案更新答案,它可能对其他人有所帮助,因为我的答案旨在指出 ASP.NET 会话状态行为
【解决方案2】:

那为什么这在干净的项目中效果很好,但在大型项目中却不行?

async/await 仅在 .NET 4.5 上运行时才能正常工作。

要升级旧的 ASP.NET 项目,您必须执行两个步骤:

  1. 将目标框架更改为 .NET 4.5(或更高版本)。
  2. httpRuntime.targetFramework setting in your web.config 更改为“4.5”(或更高版本)。

当您将现有的 ASP.NET 项目升级到最新版本的 .NET 时,Visual Studio 将执行上述第一步,而您必须手动执行第二步。但是,如果您在最新版本的 .NET 上创建新的 ASP.NET 项目,Visual Studio 将完成这两个步骤。

【讨论】:

  • 讲道理斯蒂芬。我通过使用 [SessionState(SessionStateBehavior.Disabled)] 控制器注释解决了这个问题。我已经从安全的角度进行了验证。在大型项目 web.config 中,我没有找到任何 httpRuntime 词。但是我也可以看到 ,我看到 system.webServer 的处理程序条目仍然指向 4.0 框架。让我检查一下,如果此更改有帮助。
  • 不,我仍然看到有行为。
  • @AbhimanyuKumarVatsa: async 不会改变会话状态的工作方式,因此您应该尽可能禁用会话状态,就像同步方法一样。但是,我的回答中的其他信息非常重要:async/await 的行为完全未定义,除非您设置 httpRuntime.targetFramework
【解决方案3】:

为了解决这个问题,我刚刚在控制器中添加了[SessionState(SessionStateBehavior.Disabled)],您可以在下面看到:

[SessionState(SessionStateBehavior.Disabled)]
public class UploadController : Controller
{
    [HttpPost]
    [ValidateInput(false)]
    public async Task<JsonResult> VideoUpload(string Id)
    {
        for (int i = 0; i < Request.Files.Count; i++)
        {
            // :::::
            await Run(fileStream);
        }

        return Json(new { error = false, message = "File uploaded." });
    }

    public async Task Run(Stream fileStream)
    {
        // :::::

        using (fileStream)
        {
            // A long running method call
            await fileUploadRequest.UploadAsync();
        }
    }

    [HttpGet]
    public JsonResult GetUploadingStatus()
    {
        // :::::
        return Json(new { statusMessage = statusMessage, totalSent = totalSent, totalSize = totalSize }, JsonRequestBehavior.AllowGet);
    }
}

使用此注释可能会导致一些安全漏洞,因此请在注释控制器之前自行验证。

希望你觉得这很有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多