对Action方法的两个并行ajax请求被排队,为什么? [英] Two parallel ajax requests to Action methods are queued, why?

查看:87
本文介绍了对Action方法的两个并行ajax请求被排队,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ASP.NET MVC开发视频网站.

I'm developing a video website using ASP.NET MVC.

我想在我的应用程序中拥有的一项功能是跨视频.但是由于转码过程可能非常耗时,因此我想向客户端用户显示该过程的进度.

One functionality I want to have in my application is transocding video. But as the transcoding process could be very time-consuming, I want to show the progress of that process to the client user.

因此,我的模式是使用一个控制器动作来处理整个代码转换过程,并将其进度写入存储在服务器上的文件中.同时,我使用Ajax调用另一个控制器操作来读取指定的文件,检索进度信息,并将其在转码过程中每2秒发送回客户端以供显示.

So, my schema is to use one controller action to handle the whole transcoding process and write its progress into a file stored on the server. Meanwhile I use Ajax to call another controller action to read the specified file, retrieve the progress information and send it back to the client for display every 2 seconds during the transcoding process.

为了实现我的计划,我编写了以下代码:

To fulfill my plan, I have written the following code:

服务器端:

public class VideoController : Controller
{
         //Other action methods
         ....
    //Action method for transcoding a video given by its id
    [HttpPost]
    public async Task<ActionResult> Transcode(int vid=0)
    {
        VideoModel VideoModel = new VideoModel();
        Video video = VideoModel.GetVideo(vid);
        string src = Server.MapPath("~/videos/")+video.Path;
        string trg = Server.MapPath("~/videos/") + +video.Id+".mp4";
        //The file that stores the progress information
        string logPath = Server.MapPath("~/videos/") + "transcode.txt";
        string pathHeader=Server.MapPath("../");
        if (await VideoModel.ConvertVideo(src.Trim(), trg.Trim(), logPath))
        {
            return Json(new { result = "" }); 
        }
        else
        {
          return Json(new { result = "Transcoding failed, please try again." });
        }
    }
    //Action method for retrieving the progress value from the specified log file
    public ActionResult GetProgress()
    {
        string logPath = Server.MapPath("~/videos/") + "transcode.txt";
        //Retrive the progress from the specified log file.
        ...
        return Json(new { progress = progress });
    }
}

客户端:

var progressTimer = null;
var TranscodeProgress=null;
//The function that requests server for handling the transcoding process
function Transcode(vid) {
   //Calls the Transcode action in VideoController
    var htmlobj = $.ajax({
        url: "/Video/Transcode",
        type: "POST",
        //dataType: 'JSON',
        data: { 'vid': vid },
        success: function(data)
        {
        if(data.result!="")
            alert(data.result);
        }
        else
        {
          //finalization works
          ....
        }
    }
    });
    //Wait for 1 seconds to start retrieving transcoding progress
    progressTimer=setTimeout(function ()
    {
        //Display progress bar
        ...
       //Set up the procedure of retireving progress every 2 seconds
        TranscodeProgress = setInterval(Transcoding, 2000);
    }, 1000);
}

//The function that requests the server for retrieving the progress information every 2 seconds.
function Transcoding()
{
    //Calls the GetProgress action in VideoController
    $.ajax({
        url: "/Video/GetProgress",
    type: "POST",
    //dataType: 'JSON',
    success: function (data)
    {
        if (data.progress == undefined || data.progress == null)
            return;
        progressPerc = parseFloat(data.progress);
        //Update progress bar
        ...
    }
  });
}

现在,客户端代码和Transcode操作方法都可以正常工作.问题在于,在Transcode操作完成其整个过程之前,将永远不会调用GetProgress方法.那么我的代码有什么问题呢?我该如何修改它以使这两个动作自发地实现我的目标?

Now the Client-side code and the Transcode action method all work fine. The problem is that the GetProgress method will never get called until the Transcode action finishes its whole procedure. So what's wrong with my code? How can I modify it to make those two actions work spontaneously so as to achieve my goal?

更新:

基于Alex的回答,我发现我的问题是由Asp.Net框架的会话锁定机制引起的.因此,在执行转码视频的操作方法时,禁用我的VideoControllerSessionState或将其设置为只读确实会使控制器对检索转码进度的请求做出响应.但是因为我在VideoController中使用Session来存储一些变量以供多个请求使用,所以这种方式不是解决我的问题的合适方法.有更好的解决方法吗?

Based on Alex's answer, I found that my problem is caused by the session lock mechanism of Asp.Net framework. So disabling the SessionState of my VideoController or setting it as read-only does make the controller responses to the request for retrieving transcoding progress when the action method of transcoding video is being executed. But because I use Session in my VideoController to store some variables for use across multiple requests, this way couldn't be a suitable solution for my problem. Is there a better way to solve it?

推荐答案

您误解了有关异步/等待的全部知识.对于每个单个请求,都会返回一个响应,这一事实并没有改变.当您在操作中呼叫等待时,还没有任何内容返回给客户端.它所做的唯一事情(在非常高级的抽象中)是将处理该请求的当前线程释放到线程池,以便可以将其用于处理其他请求.因此,基本上,它使您可以更有效地使用服务器资源,因为不会浪费任何线程来等待较长的I/O操作完成. I/O操作完成后,将继续执行操作(要求等待).仅在操作结束时,响应才会发送到客户端.

You misunderstood the whole point about async/await. It doesn't change the fact that for each single request, there is a single response that is returned. When you call await in your action, nothing is returned to client yet. The only thing it does (in a very high level abstraction) is to release the current thread that handles this request to a thread pool so it could be used for processing other requests. So basically it allows you to use your server resources more efficiently since there are no threads that are wasted waiting for long I/O operations to complete. Once the I/O operation is completed the the execution of the action (that called for await) continued. Only at the end of an action the response is sent to the client.

对于您的情况,如果它是一项长期运行的任务,那么我将使用某种后台处理解决方案,例如 Hangfire ,然后使用SignalR从服务器推送更新.此处是一个示例

As for you scenario, if it is a long running task, I would use some kind of background processing solution such as Hangfire and use SignalR to push updates from server.Here is an example

您还可以自己实施类似的操作(示例).

You can also implement something similar on your own (example).

更新: 正如@Menahem在他的评论中所说,我可能会误解您的部分问题.

UPDATE: As @Menahem stated in his comment I maybe misinterpreted part of your question.

请求排队问题可能是由于 MvcHandler 由ASP.NET MVC使用的处理程序标记为 IRequiresSessionState 接口,每个会话一次只能处理一个请求.为了更改此设置,请使您的控制器处于无会话状态(或至少确保您未在​​此控制器中写入会话),然后将其标记为 [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]属性.

Request queuing issue may be caused by incorrect configuration of SessionStateBehavior. Since MvcHandler handler which is used by ASP.NET MVC is marked with IRequiresSessionState interface, only one request at time could be processed per session. In order to change that, make you controller sessionless (or ar least make sure that you are not writing into session in this controller) and mark it with [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] attribute.

这篇关于对Action方法的两个并行ajax请求被排队,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆