长轮询停止其他请求1或2分钟

在创建聊天系统期间,我使用长生命请求来获取消息,并使用jquery请求发送如下消息:

* 发送:*

$("#btn").click(function () { $.ajax({ type: "POST", url: "Chat.aspx/Insert", data: "{ 'Str' :'" + $("#txtStr").val() + "' }", contentType: "application/json; charset=utf-8", dataType: "json", success: function (data) { }, error: function () { } }); }); 

收到:

 function Refresh() { $.ajax({ type: "POST", url: "Chat.aspx/GetRecords", data: "{ 'Id' : " + $("#hdnV1").val() + "}", success: function (data) { $.each($(data.d), function () { //Show it to user }); }, complete: function () { return Refresh(); }, contentType: "application/json; charset=utf-8", dataType: "json", traditional: true, async: true }); } 

这是我的服务器端代码来获取消息:

 [WebMethod] public static object GetRecords(int Id) { TestEntities db = new TestEntities(); int count = 0; while (true) { if (count++ >= 300) return null; System.Threading.Thread.Sleep(1000); var list = db.Commets.Where(rec => rec.Id > Id).Select(rec => new { Id = rec.Id, Str = rec.Str }).ToList(); if (list.Count > 0) return list; } } 

当用户写入内容并单击“发送”按钮时,请求将进入挂起状态,因为长寿命请求正在执行

我用萤火虫检查它们,有没有人在那里帮助我!?! 有关详细信息,请评论我,抱歉我的英语语法不好,我是英语新手

谢谢

这不是在asp.net中构建聊天的最佳方法。 随着用户数量的增加,此方法将无法扩展。

看看SignalR是构建聊天应用程序的好选择。

但是,如果您确实希望自己出于某种原因自行完成,那么在asp.net中构建聊天的最有效方法是使用IHttpAsyncHandler和ajax请求。

Asp.net的工作线程数量有限。 让其中一个进入睡眠状态只会在相对较少的用户中杀死您的应用程序。

异步请求允许您延迟请求的响应,直到发生外部事件。
用户调用此处理程序并等待某人向他发送消息。
邮件会在您发送给用户后立即发送。

收到消息后,客户端发出另一个请求并等待下一条消息。 这是保持持久连接打开的方式,允许服务器将数据推送到客户端。

这比轮询站点以检查消息是否已到达要高效得多。
使用异步处理程序还可确保在用户等待消息到来时不会浪费任何asp.net线程。 使用计时器进行轮询,您将很快用完线程来处理asp.net中的请求。

这可确保即使网站用户数量增加,您的聊天也可以很好地扩展。

这是一个完全可以实现的项目 ,以及ajax。

避免使用数据库作为站点上用户之间的通信方法。 如果要记录聊天记录,请进行所有写入异步调用。

由于您在评论中写道您在应用程序中使用了Session状态,因此长时间运行的请求阻止更新可能是正确的。

原因是Asp.Net阻止了对Session并发访问。 有关详细信息,请参阅MSDN上的此链接 。 具体来说(靠近页面底部):

但是,如果对同一会话发出两个并发请求(通过使用相同的SessionID值),则第一个请求将获得对会话信息的独占访问权。 第二个请求仅在第一个请求完成后执行。

修复它的一种方法可能是在相关页面上设置EnableSessionState="ReadOnly"EnableSessionState="False" 。 这假设您不需要使用聊天系统访问特定页面中的Session

您应该异步发送Insert,就像使用GetRecords一样。 这应该可以解决你的问题。 将async: true添加到发送请求。

问题是GetRecords可能永远不会返回。 其中,除非你使用像WebSockets这样的东西是一个问题。 这意味着连接将永远不会完成(直到它超时),并且您很可能不会从中接收任何数据。

你应该做的是让GetRecords返回,然后每隔X秒在你的jQuery中轮询一次新记录。

您还可以尝试在while循环中添加Sleep (以及最大循环限制)以允许其他线程在系统中工作并防止无限循环。 即

 int maxLoops = 50; int loopNum = 0; while (loopNum < maxLoops) { var list = db.Commets.Where(rec => rec.Id > Id).Select(rec => new { Id = rec.Id, Str = rec.Str }).ToList(); if (list.Count > 0) return list; Thread.Sleep(250); //Wait 1/4 of a second loopNum++; }