【问题标题】:Async MVC.NET action method blocks any other HTTP requests异步 MVC.NET 操作方法阻止任何其他 HTTP 请求
【发布时间】:2018-04-06 23:23:12
【问题描述】:

(我为改变问题而道歉)

以下 sn-p 来自 MVC.NET 控制器 (.NET: v4.5; AspNet.MVC: v5.2.3)。 LongOperation 被调用后,它:

  • 产生一个进程
  • 等待完成
  • 监控一些 LOG 文件
  • 使用 SignalR 通知浏览器日志文件的进度

(为简单起见,我省略了代码)

所有这些都有效,只有在 LongOperation 运行时,控制器不会处理其他 HTTP 请求。

LongOperation完成之后处理它们并且操作方法将结果返回给AJAX调用。

我在搞砸什么? 提前谢谢你。

更新(@angelsix 评论): 这是一个简化的设置:

  • 我已按照建议删除了 async/await
  • 按照建议添加断点
  • 已验证它们已按上述说明命中

基本上:相同的结果,请参阅 console.log-ed 文本和时间戳 将感谢社区的任何帮助。 提前谢谢!

图形用户界面和日志

Action methods in the Controller

[AjaxOnly]
public ActionResult _RunLongOperation(string hubId)
{
    try
    {
        for (int i = 0; i < 10; i++)
        {
            Thread.Sleep(1000);
            ProgressNotifierHub.Notify(hubId, string.Format("Notification from _RunLongOperation {0}", i));
        }
        return new HttpStatusCodeResult(HttpStatusCode.OK, "_RunLongOperation : OK");
    }
    catch (Exception)
    {
        return new HttpStatusCodeResult(HttpStatusCode.BadRequest, "_RunLongOperation : NOK");
    }
}

[AjaxOnly]
public ActionResult _RunAnotherOperation(string hubId)
{
    return new HttpStatusCodeResult(HttpStatusCode.OK, "_RunAnotherOperation : OK");
}

Razor View (partial) and javascript with SignalR hub setup Ajax calls

<script src="~/signalr/hubs"></script> 

@{ 
    Layout = null;
}

<button id="longOperationBtn" type="button" class="t-button" style='width: 155px'>Long Operation</button>
<button id="anotherOperationBtn" type="button" class="t-button" style='width: 155px'>Another Operation</button>


<script type="text/javascript">

    $(function () {
        setupEventHandlers();
        setupProgressNorificator();
    });


    function setupEventHandlers() {

        $('#longOperationBtn').click(function (event) {
            requestOperation('_RunLongOperation')
        });

        $('#anotherOperationBtn').click(function (event) {
            requestOperation('_RunAnotherOperation')
        });
    }

    function requestOperation(method) {
        trace(method + ' requested');

        $.ajax({
            url: '/Profiles/Validate/' + method,
            type: 'GET',
            data: { hubId: $.connection.hub.id },
            contentType: 'application/json; charset=utf-8',
            success: function () {
                trace(method + ' completed');
            },
            error: function () {
                trace(method + ' failed');
            }
        });
    }

    function setupProgressNorificator(profileId) {
        var hub = $.connection.progressNotifierHub;
        hub.client.notify = function (notification) {
            console.log(notification);
        };
        $.connection.hub.start();
    }

    function trace(s) {
        console.log('[' + new Date().toUTCString() + '] ' + s);
    }

</script>

【问题讨论】:

  • 澄清一下 - 长操作确实返回,已验证。
  • 你能解释更多,比如添加你的场景的完整序列吗?
  • 当然:我在加载文档时初始化 SignalR.js 集线器。单击按钮后,我对 _RunLongOperation 操作方法进行 AJAX 调用。它调用 LongOperaion() 方法,该方法生成一个外部进程,监视日志文件并通过 SignalR 集线器回复进度。这可行,但不可能有其他 HTTP 请求 - 在浏览器中的其他位置导航被阻止并在 AJAX 调用获得结果后继续。
  • 我们需要查看两个调用的来源(审查调用),并且您是否在每个操作的开头放置一个断点,因为它们应该在调用时立即到达该操作,没有什么会阻止它跨度>
  • 这不是 MVC 的工作方式。您阻止了一个操作方法,它不会阻止另一个调用。否则整个网络都会倒塌。想象整个谷歌网站一次只为数十亿个搜索结果提供服务? stackoverflow.com/questions/1763775/…。正如我之前提到的,我们仍然需要更多信息,因为您的代码现在是这样,没有阻塞问题。即使您说 Thread.Sleep(10000000) 您也可以立即拨打该电话两次没问题

标签: c# asp.net async-await signalr task


【解决方案1】:

您似乎正在 Chrome 上运行客户端“测试”。我不确定 2018 年的限制是什么(它似乎随着版本的不同而变化),但浏览器确实限制了同一主机允许的并发连接数。我相信 Chrome 的限制是 6 或 8。

您发布的日志似乎来自客户端。如果是,您看到的行为实际上可能是客户端等待免费连接以连接到服务器 - 问题可能根本不在于 ASP.NET,而在于您的测试方式。

这很容易验证 - 编写另一个测试,您可以在单独的浏览器窗口中与当前测试同时运行,该窗口只调用“短”操作。如果它有延迟,我错了。如果没有,希望我能帮上忙!

【讨论】:

  • 谢谢乔,这有帮助。使用 Chrome(用于长时间操作)和 IE(用于其他任何操作)不会导致阻塞。剩下的问题是所有这些连接来自哪里?我有 2 个 Ajax 请求(“长”和“其他”请求)和 SignalR 轮询。这是我在 Chrome 的网络窗口中看到的。这些是 3,而不是 6。有什么想法吗?再次感谢!
  • 我必须在测试应用程序被“阻止”时查看网络选项卡。
【解决方案2】:

问题

您的回复没有提及任何关于缓存的内容。所以我怀疑浏览器正在缓存响应并使用它。

验证

验证在浏览器中按F12打开developer tools,然后查看第二个响应是否显示状态304或状态缓存

解决

为了防止对动作进行缓存,在动作内部你要这样做

Prevent Caching in ASP.NET MVC for specific actions using an attribute

【讨论】:

  • 感谢您的建议。问题不同 - 我更新了他的问题。
  • 好的,我们仍然需要更多信息来诊断它。例如,在浏览器中按 F12,然后转到网络。单击按钮并观看呼叫出现。你应该采取行动。再次单击它,您会得到什么结果?请将所有这些添加到问题中,否则很难准确诊断而无需猜测
【解决方案3】:

根据this

某些 ... 协议,例如 HTTP Polling (XHR),每个 ... 客户端最多使用两个同时连接。重要的是要了解最大连接数是每个浏览器而不是每个浏览器选项卡。尝试在同一浏览器中运行多个客户端可能会导致达到此限制。

就我而言,SignalR 客户端使用的是长轮询。 Afried 报告说,当使用 Web 套接字时,没有阻塞问题。结束话题。 感谢乔的帮助。

【讨论】:

  • 很高兴我能帮上忙。祝你好运!
【解决方案4】:

您需要将控制器设置为只读会话状态行为。然后,您可以在运行长控制器方法期间向控制器发出 ajax 请求。在其他情况下(作为您抱怨的那个),请求将在完成控制器操作调用后排队并立即调用。把它放在控制器类定义之前

[SessionState(SessionStateBehavior.ReadOnly)]

【讨论】:

  • 请保持文明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多