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

时间:2012-08-03 08:18:11

标签: c# jquery asp.net long-polling

在创建聊天系统期间,我使用长生命请求来获取消息,并使用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;

    }
}

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

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

由于

4 个答案:

答案 0 :(得分:3)

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

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

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

Asp.net的工作线程数量有限。即使对于相对较少的用户,将其中一个置于睡眠状态也会导致您的应用程序失效。

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

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

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

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

这是completely working project that implements this和ajax。

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

答案 1 :(得分:2)

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

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

  

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

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

答案 2 :(得分:0)

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

答案 3 :(得分:0)

问题是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++;
}