数日前、私はこの質問をしました:
同じコントローラーアクションで6つのjQuery非同期ajaxリクエストをほぼ同時に実行します。各リクエストが返されるまでに10秒かかります。
アクションメソッドへのリクエストのデバッグとログ記録により、リクエストがシリアル化され、並行して実行されることはありません。つまり、log4netログに次のようなタイムラインが表示されます:
2010-12-13 13:25:06,633 [11164] INFO-Got:1156 2010-12-13 13:25:16,634 [11164] INFO-Returning:1156 2010-12-13 13:25:16,770 [7124] INFO-Got:1426 2010-12-13 13:25:26,772 [7124] INFO-Returning:1426 2010-12 -13 13:25:26,925 [11164] INFO-Got:1912 2010-12-13 13:25:36,926 [11164] INFO-Returning:1912 2010-12-13 13: 25:37,096 [9812] INFO-Got:1913 2010-12-13 13:25:47,098 [9812] INFO-Returning:1913 2010-12-13 13:25:47,283 [ 7124] INFO-Got:2002 2010-12-13 13:25:57,285 [7124] INFO-Returning:2002 2010-12-13 13:25:57,424 [11164] INFO-取得済み:1308 2010-12-13 13:26:07,425 [11164] INFO-Returning:1308
FireFoxのネットワークタイムラインを見ると、次のことがわかります。
上記のログサンプルとFirefoxネットワークタイムラインの両方は、同じリクエストセットに対するものです。
同じページからの同じアクションへのリクエストはシリアル化されていますか?同じセッション内のSession
オブジェクトへのシリアル化されたアクセスを知っています、ただしセッションデータは変更されていません。
クライアント側のコードを1つのリクエスト(最も長く実行されているもの)に落としましたが、これはブラウザをブロックします。つまり、ajaxリクエストが完了すると、ブラウザはリンクのクリックに応答します。
ここで私が観察しているのは(Chromeの開発者ツールで)、長時間実行されているajaxリクエストが実行されているときにリンクをクリックすると、ブラウザーが強制終了(または強制終了しようとしていることを示すFailed to load resource
エラーをすぐに報告することです待っていますか?)ajaxリクエスト:
ただし、ブラウザは新しいページにリダイレクトするにはまだ時間がかかります。
Ajaxリクエストは本当に非同期ですか、それともJavaScriptは実際にはシングルスレッドであるため、この手軽さですか?
私のリクエストはこれが機能するのに時間がかかりすぎていますか?
この問題はFirefoxで発生し、IEも同様です。
また、$.ajax
を直接使用し、async: true
を明示的に設定するようにスクリプトを変更しました。
これをIIS7.5で実行していますが、Windows 2008R2とWindows 7の両方のフレーバーは同じことを行います。
デバッグビルドとリリースビルドも同じように動作します。
答えは私を正面から見つめていた。
ASP.NETセッション状態へのアクセスはセッションごとに排他的です。つまり、2人の異なるユーザーが同時リクエストを行うと、各セッションへのアクセスが同時に許可されます。ただし、同じセッションに対して2つの同時要求が(同じSessionID値を使用して)行われた場合、最初の要求はセッション情報への排他的アクセスを取得します。 2番目のリクエストは、最初のリクエストが終了した後にのみ実行されます。
わずらわしいことに、私は数週間前にこの段落をざっと読み、大胆な文章の影響を完全には取り入れていませんでした。私は、「セッション状態へのアクセスがシリアル化される」ではなく」と読みました。すべてのリクエストは、セッション状態に触れるかどうかに関係なく、リクエストが同じセッションから送信された場合は、「シリアル化」。
幸いなことに、ASP.NET MVC3には回避策があり、セッションレスコントローラーを作成できます。スコット・ガスリーはここでこれらについて話します:
MVC3 RC2をインストールし、プロジェクトをアップグレードしました。問題のコントローラーを[SessionState(SessionStateBehavior.Disabled)]
で装飾すると問題が解決します。
もちろん、通常は数分前にStack Overflowでこれを見つけました。
これを再現しようとしていましたが、できませんでした。私のテストは次のとおりです。
_private static readonly Random _random = new Random();
public ActionResult Ajax()
{
var startTime = DateTime.Now;
Thread.Sleep(_random.Next(5000, 10000));
return Json(new {
startTime = startTime.ToString("HH:mm:ss fff"),
endTime = DateTime.Now.ToString("HH:mm:ss fff")
}, JsonRequestBehavior.AllowGet);
}
_
そして呼び出し:
_<script type="text/javascript" src="/scripts/jquery-1.4.1.js"></script>
<script type="text/javascript">
$(function () {
for (var i = 0; i < 6; i++) {
$.getJSON('/home/ajax', function (result) {
$('#result').append($('<div/>').html(
result.startTime + ' | ' + result.endTime
));
});
}
});
</script>
<div id="result"></div>
_
そして結果:
_13:37:00 603 | 13:37:05 969
13:37:00 603 | 13:37:06 640
13:37:00 571 | 13:37:07 591
13:37:00 603 | 13:37:08 730
13:37:00 603 | 13:37:10 025
13:37:00 603 | 13:37:10 166
_
FireBugコンソール:
ご覧のとおり、AJAXアクションは並行してヒットします。
更新:
私の最初のテストでは、リクエストは実際にFireFox 3.6.12とChrome 8.0.552.215で $.getJSON()
を使用するときにキューに入れられます。 IE8では問題ありませんが、テストはASP.NET MVC 2プロジェクト、VS2010、Cassini Webサーバー、Windows 7 x64ビットで実行されました。
$.getJSON()
を $.get()
に置き換えると、すべてのブラウザーで問題なく動作します。そのため、この$.getJSON()
にはリクエストがキューイングされる可能性があるものがあると信じられます。 jQueryフレームワークの内部に精通している誰かが、この問題をさらに明らかにできるかもしれません。
更新2:
_cache: false
_を設定してみてください:
_$.ajax({
url: '/home/ajax',
cache: false,
success: function (result) {
$('#result').append($('<div/>').html(
result.startTime + ' | ' + result.endTime
));
}
});
_