gpt4 book ai didi

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

转载 作者:太空狗 更新时间:2023-10-29 21:16:33 26 4
gpt4 key购买 nike

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

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

因此,我的方案是使用一个 Controller 操作来处理整个转码过程,并将其进度写入存储在服务器上的文件中。同时我在转码过程中每2秒使用Ajax调用另一个controller action读取指定文件,获取进度信息并发送回客户端显示。

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

服务器端:

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 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 操作方法都可以正常工作。问题在于,在 Transcode 操作完成其整个过程之前,永远不会调用 GetProgress 方法。那么我的代码有什么问题呢?我怎样才能修改它,使这两个 Action 自发地工作,从而实现我的目标?

更新

根据Alex的回答,我发现我的问题是由Asp.Net框架的session锁机制引起的。所以禁用我的VideoControllerSessionState或者将其设置为只读确实使得 Controller 在执行转码视频的action方法时响应获取转码进度的请求.但是因为我在我的 VideoController 中使用了 Session 来存储一些跨多个请求使用的变量,所以这种方式不是解决我的问题的合适方法。有没有更好的办法解决?

最佳答案

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

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

您也可以自己实现类似的功能 (example)。

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

请求排队问题可能是由于SessionStateBehavior配置不正确引起的.自 MvcHandler ASP.NET MVC 使用的处理程序标有 IRequiresSessionState接口(interface),每次 session 只能处理一个请求。为了改变它,让你的 Controller 无 session (或者至少确保你没有写入这个 Controller 中的 session )并将其标记为[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)] 属性。

关于c# - 对 Action 方法的两个并行 ajax 请求排队,为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40447801/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com