質問者
Response.flushについて

質問
-
いつもお世話になっております。
ASP.NETの勉強中の初級PGと申します。
Visual Web Developer 2005 にて開発しています。
Response.flush()の動きで質問があります。
自作プログレスバーを作成し開発環境でテストを行い、サーバーにWebアプリを
配置した所、Response.Flush()処理が著しく遅くなってしまいます。
開発環境のデバッグ開始で行うとSleep通りにゲージが進んでいくのですが…。
IISの設定かなにかが足りないのでしょうか?
下記のJavaScriptを書き出すようにしています。
<html>
<head>
<body>
<form>
<div style="position:absolute;background-color:Blue;" id="bar"></div>
<%
For i As Integer = 0 To 100
Response.Write("<script language='javascript' type='text/javascript'>" & vbCrLf)
Response.Write("<!--" & vbCrLf)
Response.Write("window.bar.style.pixelWidth = '" & i & "';" & vbCrLf)
Response.Write("//-->" & vbCrLf)
Response.Write("</script>" & vbCrLf)
Response.Flush()
NextSystem.Threading.Thread.Sleep(10)
%>
</form>
</body>
</head>
</html>
開発機 WindowsXP Pro Ver2002 SP2
サーバー Windows2000 SP4
すべての返信
-
まず、初級PGさんが提示されたコードで、クライアントとサーバでどのような処理が
おこなわれているかを、考えてみましょう。
で、ブラウザに表示されたHTMLソースコードを一度確認してみてください。どのようなソースが生成されていますか?
一応、初級PGさんのコードでいうなら、For ループの外に Thread.Sleep があるのが原因とは思いますが、
このコードそのものの処理はあまり良いものとは言えません。
あくまでも例ですが、このような処理は下記のコードのようにクライアント側のスクリプトでおこなうのが妥当と思います。
Code Snippet<html>
<head runat="server">
<title>hoge</title>
</head>
<body>
<form id="form1" runat="server"><div style="position:absolute;background-color:Blue;" id="bar"></div>
</form>
<script type="text/javascript">
var count = 0;
var timerId = window.setInterval("onInterval()", 10);
function onInterval()
{
window.bar.style.pixelWidth = ++count;
if (count >= 100)
window.clearInterval(timerId);
}
</script>
</body>
</html> -
chack - Akira Inoue さん どうもありがとうございます。
Thread.Sleepの位置はこちらの引用ミスでした。すいません。
私がやりたい事も合わせてプログラムを書き足しました。
イメージ的には、サーバー側で1-n件数の処理を行う関数の進捗率(プログレスバー)をブラウザに書き出したく
このようなプログラムの設計になりました。
このプログラムで、サーバーにWebアプリを設置して動かすのと、開発環境でWebアプリを動かした時の
Response.Flush()が走るタイミングに差異があるのがわかりません。
(開発環境では一瞬で処理が終わるのに、サーバーに設置すると プログレスバーの進みがやたら遅いです)
Code Snippet<html>
<head runat="server">
<title>hoge</title>
</head>
<body>
<form id="form1" runat="server">
<div style="position:absolute;background-color:Blue;" id="bar"></div>
</form>
<%
For i As Integer = 0 To n'ここに処理時間がまちまちな関数をいれたい。
Call Hoge()Response.Write("<script language='javascript' type='text/javascript'>" & vbCrLf)
Response.Write("<!--" & vbCrLf)
Response.Write("window.bar.style.pixelWidth = '" & i & "';" & vbCrLf)
Response.Write("//-->" & vbCrLf)
Response.Write("</script>" & vbCrLf)
Response.Flush()
System.Threading.Thread.Sleep(10)Next
%>
</body>
</head>
</html> -
個人的にはあまりお勧めできない方法ということは変わりありませんが、
とりあえず初級PGさんのソースコードで進めたとすると・・・
まず、
開発環境:クライアント-サーバは同一PC
実行環境:クライアント-サーバは異なるPC
ですよね。
で、Thread.Sleep(10) とは 10msec のスリープ時間ですが、
異なるPC間での通信速度は考慮されていますか?
試しに、Thread.Sleep(1000) として、開発環境と実行環境で比較してみたらどうなるでしょうか。
※正確な進捗状況をプログレス表示したいというお気持ちはわかりますが、別の方法として
アニメーションGIFを用意し、その画像を処理中のあいだだけ表示する手法が簡単でよく使われています。
-
chack - Akira Inoue さん ありがとうございます。
おっしゃる通り、異なるPC間での通信速度が頭にありませんでした。
Thread.Sleepを1000にした所、二つの環境で表示速度が同一になりました。
疑問に残ったことがひとつあります。
調査の為に、異なるPCに「ASP」で同じ処理を書いた所、Thread.Sleepがない為一瞬でプログレスバーが表示されました。
あれ?と思い「ASP.NET」の方でThread.Sleepを消した同じ処理のプログレスバーの表示が一瞬で表示されません。
(ひとつひとつのJavaScriptが1秒弱かかって表示されている用な感じです。)
これは、ASP.NETのセキュリティみたいなものが働いているのでしょうか?
ASP.NETの設定に、通信速度やクライアントへの再送信の間隔等の設定があるのでしょうか?
-
初級PG さんからの引用 調査の為に、異なるPCに「ASP」で同じ処理を書いた所、Thread.Sleepがない為一瞬でプログレスバーが表示されました。 あれ?と思い「ASP.NET」の方でThread.Sleepを消した同じ処理のプログレスバーの表示が一瞬で表示されません。
(ひとつひとつのJavaScriptが1秒弱かかって表示されている用な感じです。)
これは、ASP.NETのセキュリティみたいなものが働いているのでしょうか?
セキュリティ云々は関係ないと思います。
今、こちらの環境で簡単に試してみましたが、両者に違いは見受けられませんでした。
(結果は ASP / ASP.NET ともすぐに表示される)
環境は、下記の通りです。
サーバ:Windows Server 2003 / IIS6.0
クライアント:Windows XP SP2 / IE7.0
両方の PC とも同じローカルネットワーク内にある環境です。
両者とも
Response.Buffer = True ( or Resposne.BufferOutput = true )
の状態で、ループ内で
Response.Flush()
をおこなっているのなら、同じ動作をするはずと思いますが。
ちなみに、ASP の環境と ASP.NET の環境は同じ PC ですか?それとも、異なる PC ですか?
異なる PC なら、これまた通信速度が関係してるような気がしますけど。
例えば、一方の PC がルータを介した異なるネットワークにあって、もう一方の PC が同一ネットワーク内にあるような環境ではありませんか?
いずれにしても、このような実装をおこなうにあたり、クライアント・サーバ間の通信速度やネットワーク環境、サーバ処理性能なども考慮した設計をされることをお進めします。
それと始めにも書きましたが、ブラウザに表示されたHTMLソースコードを一度確認してみてください。どのようなソースが生成されているか見てみましたか?(私個人的には、×ですね。)
P.S
正確な処理件数などの表示はできませんが、サーバ側での処理に時間がかかるような場合にこそ、
ASP.NET AJAX (UpdateProgress) などを使うのが簡単なんですけどね。
-
chack - Akira Inoue さん 大変お世話になっております。
私が調査した情報がまったくありませんでした。すいません。
調査時の環境は下記になります。
クライアント: WindowsXP Pro Ver2002 SP2 / IE6.0
サーバー: Windows2000 SP4 / IIS5.0両方とも、同じハブにつながったネットワークになっております。ルーターは挟んでいません。
ASPの環境と、ASP.NETの環境は同じです。(同一サーバーにASP用とASP.NET用の仮想ディレクトリを構築しています)
原因がわからず、その後自分なりに調査を進めていました。
ASP.NET環境のテストで、ループの間にファイルをコピーする処理をいれました。
(サーバーにあるオリジナルファイルのコピーを100個作成。)
処理を流してみたのですが、フォルダには100個のコピーが出来ているのに、
ブラウザ上のプログレスバーの進捗がまったくついてこない感じです。
ひとつのJavaScriptをFlushするのに0.5秒くらいかかってます。
(サーバー上の処理が終わっているのにブラウザの表示が遅い。)
ASP環境にて、同じようなファイルコピー処理を挟んだ結果は私の期待通り、
プログレスバーの進捗とファイル作成の進捗が等しくなっている感じがします。
(ブラウザの表示が終了とともにファイルコピーが出来ています)
原因がこちらでしか再現されないのがわからないので、とりあえずOSから再インストールしてみたいと思います。
ありがとうございました。