首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >两个并行的ajax请求到Action方法排队,为什么?

两个并行的ajax请求到Action方法排队,为什么?
EN

Stack Overflow用户
提问于 2016-11-06 09:26:02
回答 2查看 2.5K关注 0票数 6

我正在开发一个使用ASP.NET MVC的视频网站。

我想在我的应用程序中有一个功能是传输视频。但是,由于转码过程可能非常耗时,我想向客户端用户展示该过程的进展情况。

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

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

服务器端:

代码语言:javascript
复制
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 });
    }
}

客户端:

代码语言:javascript
复制
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 retrieving 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操作方法都可以正常工作。问题是,在GetProgress操作完成其整个过程之前,将永远不会调用Transcode方法。我的密码怎么了?我如何修改它,使这两个行动自发地工作,以实现我的目标?

更新

基于Alex的回答,我发现我的问题是由Asp.Net框架的会话锁定机制引起的。因此,当执行转换视频的操作方法时,禁用我的SessionStateVideoController或将其设置为只读确实会使控制器响应检索转码过程的请求。但是,由于我在我的VideoController中使用VideoController存储了一些变量,以便跨多个请求使用,所以这种方式不可能是解决问题的合适方法。有没有更好的办法解决这个问题?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-11-06 10:04:34

您误解了异步/等待的全部要点。这并没有改变这样一个事实:对于每个请求,都有一个返回的响应。当您在操作中调用“等待”时,尚未向客户端返回任何内容。它所做的唯一事情(在非常高级的抽象中)是将处理此请求的当前线程释放到线程池中,以便它可以用于处理其他请求。因此,基本上它允许您更有效地使用服务器资源,因为没有线程会浪费时间等待长时间的I/O操作的完成。一旦I/O操作完成,操作(调用等待)的执行就会继续。只有在操作结束时,才会将响应发送给客户端。

至于您的场景,如果这是一个长期运行的任务,我将使用某种背景处理解决方案,如汉火和使用SignalR从服务器.下面是一个例子推送更新。

您也可以自己实现类似的东西(示例)。

更新:正如@Menahem在他的评论中所说,我可能误解了你问题的一部分。

请求队列问题可能是由SessionStateBehavior的不正确配置引起的。由于由MvcHandler MVC使用的ASP.NET处理程序被标记为IRequiresSessionState接口,因此每个会话只能处理一个请求。为了改变这一点,使您的控制器没有会话(或者至少要确保您没有在此控制器中写入会话),并使用[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]属性标记它。

票数 9
EN

Stack Overflow用户

发布于 2016-11-06 09:37:33

文件创建正在阻塞调用。换句话说,直到第一个线程不关闭文件,第二个线程使报告无法读取该文件的内容。作为解决办法,您可以创建进度百分比的文件。例如,要避免阻塞对文件系统的调用,请使用movie1 1-5%. to、MOVE1-10-%. to、movie1 1-15-%.to等。然后,您可以检查,对于movie1,如果有文件file1-15%. that,那么您可以向ajax调用报告,15 %的电影被转换了。或者选择另一个非阻塞存储。例如,可以在第一个线程中向db报告结果,在另一个线程中从db读取结果。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40447801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档