Long polling Stop other request for 1 or 2 minutes
Asked Answered
G

4

2

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

Georgeta answered 3/8, 2012 at 8:18 Comment(3)
Is my question understandable enough ?!!Georgeta
Are you using Session state in the application?Lorileelorilyn
@Lorileelorilyn , What do you mean ?!! Yes I use them in all over of my project!Georgeta
D
4

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.

Damascus answered 11/9, 2012 at 4:25 Comment(2)
Your answer looks great ,I am waiting for others reply in 6 day an then will accept the best answer ,thanks for help :)Georgeta
Unfortunately using an async Controller Action that Delays until new info to push still occupies the Request Thread and rapidly leads to Thread Exhaustion on the serverPatti
M
1

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++;
}
Machicolate answered 3/8, 2012 at 8:32 Comment(6)
Then it would be short polling instead of long polling, which defeats the purposeIdeology
However, the implementation for the C# method is still flawed and will hammer the server with SQL requests. Ideally you want the long poller to be in some sort of blocking state, or at least a sleep inside the loopIdeology
@Machicolate , I tried to insert int database using SQL server management studio , and the GetRecord take it back to user and every thing going rightGeorgeta
Either way the problem is still the while loop, perhaps a Sleep may be a better solution?Machicolate
@AliForoughi Doing things through SQL Management studio will be fine, I believe the while loop is your problem. Try adding a sleep or add a maximum loop limit; see my update.Machicolate
@Machicolate , I have steel that problem, i update my code as you saidGeorgeta
L
1

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.

Lorileelorilyn answered 10/9, 2012 at 12:35 Comment(1)
i`ll check it and comment the resultGeorgeta
I
0

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.

Ideology answered 3/8, 2012 at 8:30 Comment(4)
you mean that I should use async: true for send ajax request?!!Georgeta
I am going to test what you said right now , give me some minutesGeorgeta
I have steel that problem , and your solution does not help me dudeGeorgeta
Like @Machicolate says, you're also locking up the server with an infinite loop. If you try adding a sleep in between the calls to the database, it might help things.Ideology

© 2022 - 2024 — McMap. All rights reserved.