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;

    }
}

ユーザーが何かを書き込んで[送信]ボタンをクリックすると、リクエストは保留状態になります。これは、長寿命のリクエストが実行されているためです。

私はそれらをfirebugでチェックします、私を助けるためにそこに誰かがいますか!?!詳細についてはコメントしてください、そして私の悪い英語の構文について申し訳ありません、私は英語が初めてです

ありがとう

4

4 に答える 4

4

これは、asp.net でチャットを構築する最良の方法ではありません。ユーザー数が増えると、この方法は拡張できなくなります。

SignalRは、チャット アプリケーションを構築するための適切なオプションです。

ただし、何らかの理由で自分でやりたい場合は、asp.net でチャットを構築する最も効率的な方法は、IHttpAsyncHandlerと ajax 要求を使用することです。

Asp.net のワーカー スレッドの数は限られています。それらの 1 つをスリープ状態にすると、比較的少数のユーザーであっても、アプリケーションが強制終了されます。

非同期リクエストを使用すると、外部イベントが発生するまでリクエストの応答を遅らせることができます。
ユーザーはこのハンドラーを呼び出し、誰かがメッセージを送信するまで待機します。
メッセージは、ユーザーに送信するとすぐに配信されます。

メッセージを受信すると、クライアントは別のリクエストを作成し、次のメッセージを待ちます。これは、永続的な接続を開いたままにし、サーバーがデータをクライアントにプッシュできるようにする方法です。

これは、メッセージが到着したかどうかを確認するためにサイトをポーリングするよりもはるかに効率的です。
また、非同期ハンドラーを使用すると、ユーザーがメッセージの受信を待機している間に asp.net スレッドが無駄になることはありません。タイマーを使用してポーリングすると、asp.net で要求を処理するスレッドがすぐに不足します。

これにより、サイトのユーザー数が増えてもチャットを適切にスケーリングできます.

これは、ajax とともにthis を実装する完全に機能するプロジェクトです。

サイト上のユーザー間の通信手段としてデータベースを使用することは避けてください。チャットをログに記録したい場合は、すべての書き込みを非同期呼び出しにします。

于 2012-09-11T04:25:34.787 に答える
1

アプリケーションで状態を使用しているとコメントに書いたので、Session実行時間の長いリクエストが更新をブロックしていることはおそらく正しいでしょう。

その理由は、Asp.Net が への同時アクセスをブロックするためですSession。詳細については、MSDN のこのリンクを参照してください。具体的には(ページの下部近く):

ただし、同じセッションに対して (同じ SessionID 値を使用して) 2 つの同時要求が行われた場合、最初の要求はセッション情報への排他的アクセスを取得します。2 番目の要求は、最初の要求が終了した後にのみ実行されます。

それを修正する 1 つの方法は、問題のページを設定EnableSessionState="ReadOnly"またはオンにすることです。これは、チャット システムを使用して特定のページにEnableSessionState="False"アクセスする必要がないことを前提としています。Session

于 2012-09-10T12:35:10.980 に答える
0

GetRecordsの場合と同様に、Insertも非同期で送信する必要があります。それはあなたの問題を解決するはずです。async: true送信リクエストに追加します。

于 2012-08-03T08:30:19.950 に答える
0

問題はGetRecords二度と戻らないかもしれないということです。WebSocketのようなものを使用していない限り、これは問題です。これは、接続が(タイムアウトするまで)完了せず、接続からデータを受信しない可能性が高いことを意味します。

あなたがすべきことは、GetRecordsすぐに戻って、X秒ごとに新しいレコードをjQueryでポーリングすることです。

また、whileループ(および最大ループ制限)にaを追加して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++;
}
于 2012-08-03T08:32:46.960 に答える