Async MVC.NET操作方法阻止任何其他HTTP请求

时间:2018-04-06 23:23:12

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

(我为更改问题而道歉)

以下代码片段来自MVC.NET控制器(.NET:v4.5; AspNet.MVC:v5.2.3)。 调用 LongOperation 后,它:

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

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

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

LongOperation 完成后处理,操作方法将结果返回给AJAX调用。

我搞砸了什么? 提前谢谢。

enter image description here

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

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

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

GUI和日志 GUI and log

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>

4 个答案:

答案 0 :(得分:1)

看起来你正在运行客户端&#34;测试&#34;在Chrome上。我不确定2018的限制是什么(似乎从发行版到发行版),但浏览器确实限制了允许同一主机的并发连接数。我相信Chrome的限制是6或8。

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

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

答案 1 :(得分:0)

问题

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

验证

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

解决

要防止对操作进行缓存,请执行此操作内的

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

答案 2 :(得分:0)

根据this

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

就我而言,SignalR客户端正在使用长轮询。据报道,当使用Web套接字时,没有阻塞问题。关闭主题。 感谢Joe的帮助。

答案 3 :(得分:0)

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

[SessionState的(SessionStateBehavior.ReadOnly)]