web-dev-qa-db-ja.com

ASP.NET静的変数の寿命

(Global.asaxではなく)ページクラスで定義された静的変数にいくつかの情報を保持しています。私は次のようなコードで変数を宣言するだけです:

protected static int SomeGlobalUnsecureID;
protected static string SomeGlobalUnsecureString;

pageLoadイベントで変数を定義します。たとえば、データベースからIDを確認します。SomeGlobalUnsecureIDと異なる場合は、他の場所からSomeGlobalUnsecureIDとStringを更新します。それ以外の場合はそのままにします。これは私のアプリでは完全に安全です。ロジック(つまり、これらのデータは安全ではなく、誰でもアクセスできますが、問題ありません);私が達成したいのは

  1. 接続しているユーザーに関係なく、同じ量のメモリを保持します

  2. 永続的な情報が「メモリ」内の情報と異なる場合にのみ変更します(実際に文字列を読み取るのに時間がかかるためです)。

ここで、PageLoadでチェックを行うため、リロードされたページに問題はありません。しかし、私のページはWebMethodsで一杯であり、静的変数がゼロになっていることがあります。そして奇妙な部分は次のとおりです。静的変数がゼロに設定されていても、セッションは引き続きアクティブです(つまり、サーバーまたはアプリプールの再起動などはありません)。

これは私にとって本当に奇妙です。静的変数は、アプリケーションが(何らかの形で)終了するまでその値を保持すると想定しています。ただし、セッションの有効期限が切れていない場合でも、静的変数はゼロになります。何を指示してるんですか?アプリケーション変数を使用するほうが良い選択ですか? Webで読んだすべてのドキュメントは、アプリケーション変数の代わりに静的変数を提案していますが、何らかの形でそれらを宣言する必要がありますか?

71
paul simmons

静的変数は、アプリドメインの存続​​期間中保持されます。そのため、静的変数を「リセット」する2つの要因は、アプリドメインの再起動または新しいクラスの使用です。 aspx Pageクラスに格納された静的変数の場合、ASP.NETがaspx Pageを新しいクラスに再コンパイルし、古いページクラスを新しいクラスに置き換えようとすると、静的変数が失われる可能性があります。

これらの理由により、システムがクラスを再起動または置換することを決定した場合( 。NETは実行中のアプリドメインでクラス/アセンブリを強制終了またはアンロードしません )、新しい変数を取得しているため、静的変数がリセットされます再起動または置換を伴うクラス。これは、aspxページと App_Codeフォルダー内のクラス の両方に適用されます

何らかの理由で再コンパイルする必要があると思われる場合、ASP.NETはクラスを置き換えます( ASP.NET動的コンパイルを参照 )。

アプリドメインの再起動による静的変数の損失を防ぐことはできませんが、クラスの置き換えからそれを回避することはできます。 aspxページではなく、App_Codeディレクトリにないクラスに静的変数を配置できます。プログラムのstatic classのどこかに配置したい場合があります。

public static class GlobalVariables
{
    public static int SomeGlobalUnsecureID;
    public  static string SomeGlobalUnsecureString;
}

静的変数はプールごとです。つまり、asp.netサイトを実行するプールが2つある場合、2つの異なる静的変数があります。 ( Webガーデンモード

システムがこの方法のいずれかでasp.netアプリケーションを再起動すると、静的変数は失われます。

  1. プールは、再コンパイルする必要があると判断します。
  2. App_offline.htmファイルを開きます
  3. プールを手動で再起動します
  4. プールは、ユーザーが定義して再起動する制限に達しました。
  5. 何らかの理由で、iisまたはプールを再起動します。

この静的変数はスレッドセーフではないため、異なるスレッドからアクセスする場合は、特にlockキーワードを使用する必要があります。

アプリを再起動すると、静的データが何であれリセットされるため、本当にデータを永続化する場合は、カスタムクラスを使用してデータベースにデータを保存する必要があります。 データベースセッション状態モード を使用して、ユーザーごとの情報を セッション状態 に保存できます。 データベースではなくメモリに格納されている であるため、ASP.NETアプリケーション状態/変数は役に立ちません。したがって、アプリケーションドメインの再起動でも失われます。

93
Aristos

静的変数の寿命にとって、次の2つのポイントも重要だと思います。

1-アプリケーションプールの詳細設定で、[リサイクル]-> [通常の時間間隔(分)]設定を確認します。デフォルト値は1740です。これは、アプリケーションプールのリサイクルにより、29時間ごとに静的変数が失われることを意味します。この設定は、メモリリークの可能性の終了に使用されます。この設定は変更しません。

2-アプリケーションプールの詳細設定で、[プロセスモデル]-> [アイドルタイムアウト(分)]設定を確認します。デフォルト値は20です。これは、アプリケーションプールで20分間非アクティブになるごとに、ワーカープロセスが終了/一時停止され、静的変数が失われることを意味します。この設定は、アプリケーションプールが一定時間使用されない場合にリソースを解放するために使用されます。 0に設定すると、タイムアウトを無効にできます。

15
sotn