Long polling Stop other request for 1 or 2 minutes

2020-03-27 10:31发布

问题:

During create a chat system , I use a long life request to get message , and use a jquery request to send message like this :

*Send: *

$("#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 () {

        }
    });
});

Receive :

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
    });

}

and this is my server side code to get messages :

[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;

    }
}

When user writes something and clicks on the Send button , request goes to pending state , and I thing because the long life request is executing

I check them up in firebug, is there anybody out there to help me !?! For more details comment me please , and sorry about my bad English syntax , I am new in English

Thanks

回答1:

This is not the best method to build a chat in asp.net. As the number of users increases this method won't scale.

Take a look at SignalR is a good option to build a chat application.

However if you do want to do it yourself for some reason, the most efficient method to build a chat in asp.net is to use a IHttpAsyncHandler and ajax requests.

Asp.net has a limited number of worker threads. Putting one of them to sleep will just kill your application even for a relatively small number of users.

An async request allows you to delay the response of a request till an external event occurs.
A user makes a call to this handler and waits till someone sends him a message.
Messages are delivered as soon as you send them to a user.

On receiving a message the client makes another request and waits for the next message. This is how you keep a persistent connection open and allows the server to push data to the client.

This is a lot more efficient than polling the site to check if messages have arrived.
Using the async handler also ensures that no asp.net threads are wasted while a user waits for messages to come. Polling with a timer you will quickly run out of threads to process requests in asp.net.

This ensures that your chat can scale well even as the number of users of the site goes up.

Here is a completely working project that implements this, along with ajax.

Avoid using a database as the method of communication between users on your site. If you want to log the chats, make all the writes async calls.



回答2:

Since you wrote in a comment that you are using Session state in the application, it's likely correct that the long running request is blocking the update.

The reason is that Asp.Net blocks concurrent access to the Session. See this link on MSDN for details. Specifically (close to the bottom of the page):

However, if two concurrent requests are made for the same session (by using the same SessionID value), the first request gets exclusive access to the session information. The second request executes only after the first request is finished.

One way to fix it might be to set EnableSessionState="ReadOnly" or EnableSessionState="False" on the page in question. This assuming that you don't need access to the Session in the particular page with the chat system.



回答3:

You should be sending the Insert asynchronously as well, just like you do with the GetRecords. That should solve your issue. Add async: true to the send request.



回答4:

The problem is GetRecords may never return. Which, unless you are using something like WebSockets is an issue. It means the connection will never complete (until it times out) and you will more than likely not receive any data from it.

What you should do is let GetRecords return straight away, and then poll in your jQuery for new records every X seconds.

You could also try adding a Sleep in the while loop (as well as a maximum loop limit) to allow other threads to work in the system and to prevent an infinite loop. i.e.

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++;
}