Global.asax の共有/静的変数はリクエストごとに分離されていますか?
-
09-06-2019 - |
質問
いくつかの ASP.NET Web サービスがあり、それらはすべて共通のヘルパー クラスを共有しており、そのインスタンスを 1 つインスタンス化するだけで済みます。 サーバーごと. 。これはデータの単純な変換に使用されますが、起動時に web.config ファイルからの読み込みなどに時間がかかります。 ヘルパー クラスは 100% スレッド セーフです。これをユーティリティ呼び出しの単純なライブラリと考えてください。すべてのメソッドをクラスで共有するようにしますが、初期設定は web.config からロードしたいと考えています。 Web サービスを IIS 6.0 にデプロイし、アプリケーション プールを使用し、15 ワーカーの Web ガーデンを使用しました。
Global.asax でヘルパー クラスを Private Shared 変数として宣言し、次のように遅延読み込み Shared ReadOnly プロパティを追加しました。
Private Shared _helper As MyHelperClass
Public Shared ReadOnly Property Helper() As MyHelperClass
Get
If _helper Is Nothing Then
_helper = New MyHelperClass()
End If
Return _helper
End Get
End Property
コンストラクターにログコードがあります MyHelperClass()
, 、同じスレッド上であっても、リクエストごとに実行されているコンストラクターが表示されます。ASP.NET の重要な詳細が欠けているだけだと思いますが、MSDN はあまり役に立ちませんでした。
両方を使用して同様のことを試してみました Application("Helper")
そして Cache("Helper")
そして、リクエストごとにコンストラクターが実行されることがわかりました。
解決
絶対に必要な場合を除き、アプリケーションの状態を使用するのは賢明ではありません。リクエストごとのオブジェクトを使用することに固執すると、物事ははるかに簡単になります。ヘルパー クラスに状態を追加すると、あらゆる種類の微妙なエラーが発生する可能性があります。HttpContext.Current items コレクションを使用し、リクエストごとに初期化します。VB モジュールは必要なことを実行しますが、ステートフルにしないように注意する必要があります。
他のヒント
ヘルパーをアプリケーション状態に置くことができます。global.asax でこれを実行します。
void Application_Start(object sender, EventArgs e)
{
Application.Add("MyHelper", new MyHelperClass());
}
ヘルパーは次のように使用できます。
MyHelperClass helper = (MyHelperClass)HttpContext.Current.Application["MyHelper"];
helper.Foo();
これにより、アプリケーションの起動時に作成され、アプリケーション状態で存続する MyHelperClass クラスの単一インスタンスが作成されます。インスタンスは Application_Start で作成されるため、これはリクエストごとではなく、HttpApplication インスタンスごとに 1 回だけ発生します。
私は過去に自分のアプリでこのようなことを行ったことがありますが、それによりあらゆる種類の奇妙なエラーが発生しました。すべてのユーザーは、プロパティ内の他のユーザーのデータにアクセスできます。さらに、あるユーザーが使用中に、別のユーザーが要求したために切断される可能性もあります。
いいえ、孤立していません。