ユーザーがページspawn.aspxにアクセスすると、半ダースのスレッドが生成され、すべてのページが
((System.Web.IHttpHandler)instance).ProcessRequest(reference to spawn's HTTPContext);
ASP.Netがユーザーに1つの要求に対して7つの応答を送信しているように見え、その部分が処理され、1つの応答のみが送信されるという事実について心配する必要はありません。
問題は、多くのスレッド(クワッドクワッド)があるトラフィックの多い環境(本番環境)では、エラーが発生することです。
System.IndexOutOfRangeException at System.collections.ArrayList.Add at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, DateTime utcDepTime) at System.Web.ResponseDependencyList.AddDependencies(String[] items, String argname, Boolean cloneArray, String requestVritualPath) at System.Web.UI.Page.AddWrappedFileDependencies(Object virtualFileDependencies) at ASP.spawned_page_no_1_aspx.FrameworkInitialize() at System.Web.UI.Page.ProcessRequest
他の場所で複製することはできません。私の同僚は、これは元のHTTPContextを再利用して他のスレッドに渡しているためであり、スレッドセーフではないと考えています。
このロジックに従って、スレッドに渡す新しいHTTPContextを作成してみました。しかし、その一部は「結合」しないようです。具体的には、Sessionオブジェクトを新しいHTTPContextに取り込む必要があります。キャッシュのような他の部分も入れたいと思います。レコードの場合、HTTPContext.Current.Session.IsSynchronizedはfalseです。
私の質問は次のとおりです。
- エラーはスレッド間でHTTPContextを使用したことによるものだと思いますか?
- どうすれば修正できますか?
- 修正によって各スレッドのHTTPContextが複製されている場合、セッション(およびキャッシュ)を新しいスレッドに取り込むにはどうすればよいですか?リクエストとレスポンスはコンストラクターで行われますが、セッションは設定できません。
編集:詳細
したがって、このステートメントに戻ります。「ASP.Netがユーザーに1つの要求に対して7つの応答を送信しているように見え、その部分が処理され、1つの応答のみが送信されるという事実について心配する必要はありません。」レイモンド・チェンの大ファン、私はあなたに同意します:「今あなたは2つの問題を抱えています」はこれ以上の情報がない場合の合理的な声明です。
実際に起こっているのは、返送するExcelドキュメントを作成しているということです。spawn.aspxページでは、Excelにレンダリングしているという事実や、レンダリングを実行するオブジェクトなど、いくつかの状態情報を設定しています。生成された各ページはその情報を取得し、オブジェクトにレンダリングする順番になるまでブロックします。文字通りこのように見える場合:
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
if (this.RenderToExcel)
{
Deadlocker.SpinUntilCurrent(DeadLockToken);
RenderReport(this, this.XLSWriter);
Deadlocker.Remove(DeadLockToken);
}
else
base.Render(writer);
}
しかし、それまでのすべての処理-データベースアクセス、制御階層、すべてが並行して実行されます。そして、それはたくさんあります-それでもRenderでブロックさせながらそれを並列化すると、全体の時間が半分以上に短縮されます。
そして、その最良の部分は、Excelレンダリングのために何も書き直す必要がなかったことです。すべてのコントロールは、Excelをレンダリングする方法を知っており、生成された各ページに個別にアクセスできます(これは、実際には「通常のケース」です。Excelレポートは、生成されたすべてのページの単なる集約です)。
したがって、最終結果は「これはできません。アプローチを再考する必要があります」になると思いましたが、ロジックやコードを複製することなくすべてがうまく機能するという事実から、少なくとも試してみる必要がありました。何かを抽象化する必要があるのはとても完璧です。そして、問題となるのはマルチスレッドだけです。ページをシリアルにレンダリングすると、すべてが正常になり、遅くなります。