加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 对Action方法的两个并行ajax请求排队,为什么?

发布时间:2020-12-15 08:18:32 所属栏目:百科 来源:网络整理
导读:我正在使用ASP.NET MVC开发一个视频网站. 我想在我的应用程序中使用的一项功能是转换视频.但由于转码过程可能非常耗时,我想向客户端用户展示该过程的进度. 因此,我的架构是使用一个控制器操作来处理整个转码过程并将其进度写入存储在服务器上的文件中.同时我
我正在使用ASP.NET MVC开发一个视频网站.

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

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

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

服务器端:

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",success: function (data)
    {
        if (data.progress == undefined || data.progress == null)
            return;
        progressPerc = parseFloat(data.progress);
        //Update progress bar
        ...
    }
  });
}

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

更新:

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

解决方法

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

至于你的场景,如果它是一个长时间运行的任务,我会使用某种后台处理解决方案,如Hangfire,并使用SignalR从server.Here is an example推送更新

你也可以自己实现类似的东西(example).

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读