静的クラスインスタンスは、ASP.NETのリクエストまたはサーバーに固有ですか?


182

ASP.NET Webサイトでは、静的クラスは各Webリクエストに固有ですか、それとも、必要に応じてインスタンス化され、GCが破棄することを決定するたびにGCされますか?

私が尋ねる理由は、以前にいくつかの静的クラスをC#で作成したことがあり、その動作が予想とは異なるためです。静的クラスは各リクエストに固有であると期待していましたが、そうではありません。

それらが各要求に固有ではない場合、それらを許可する方法はありますか?

更新:
driisが私に与えた答えはまさに私が必要としたものでした。私はすでにシングルトンクラスを使用していましたが、静的インスタンスを使用していたため、ユーザーが異なっていてもリクエスト間で共有されていましたが、この場合は悪いことでした。を使用HttpContext.Current.Itemsすると、問題が完全に解決されます。将来この質問に遭遇した人のために、パターンを理解しやすいように簡略化して短縮した私の実装を以下に示します。

using System.Collections;
using System.Web;

public class GloballyAccessibleClass
{
    private GloballyAccessibleClass() { }

    public static GloballyAccessibleClass Instance
    {
        get
        {
            IDictionary items = HttpContext.Current.Items;
            if(!items.Contains("TheInstance"))
            {
                items["TheInstance"] = new GloballyAccessibleClass();
            }
            return items["TheInstance"] as GloballyAccessibleClass;
        }
    }
}

ただのfilterContext.Result = new RedirectResult(...)注意:リクエストをリダイレクトすると、たとえば、新しいHttpContextが作成されるため、アイテムが失われます。ここでは詳細:stackoverflow.com/questions/16697601/...
リウエルリベイロ

良い答えのある関連する質問は、stackoverflow.com / q / 5219431にあります。
Theophilus

回答:


146

静的クラスと静的インスタンスフィールドは、アプリケーションへのすべてのリクエスト間で共有され、アプリケーションドメインと同じ存続期間を持っています。したがって、同期の問題などが発生する可能性があるため、静的インスタンスを使用する場合は注意が必要です。また、静的インスタンスはアプリケーションプールがリサイクルされるまでGCされないため、静的インスタンスによって参照されるものはすべてGCされないことにも留意してください。これにより、メモリ使用量の問題が発生する可能性があります。

リクエストと同じ有効期間のインスタンスが必要な場合は、HttpContext.Current.Itemsコレクションを使用することをお勧めします。これは、設計上、リクエスト全体で必要なものを保存するための場所です。より良いデザインと読みやすさのために、シングルトンパターンを使用してこれらのアイテムを管理することができます。にインスタンスを格納するシングルトンクラスを作成するだけHttpContext.Current.Itemsです。(ASP.NETの共通ライブラリには、この目的のための汎用のSingletonRequestクラスがあります)。


3
シングルトンパターンのサンプルを教えていただけますHttpContext.Current.Itemsか?
Airn5475 2011

私の状況の詳細:Webアプリでは、ユーザーは共有クラスプロパティを使用するコードのクラスライブラリを実行します。このプロパティをユーザー固有にする必要がありますが、このプロパティを別の関数に渡す必要はありません。あなたが言及したデザインはこれを適切に処理できますか?
Airn5475 2011

SingletonRequestクラスを共有していただけませんか。
Tebo

静的クラスにはデータを保存していません。静的クラスは、データの取得またはデータレイヤーとしてのデータの設定にのみ使用します。何か問題はありますか?
2016年

"static instances will not be GC'ed before the application pool is recycled, and therefore everything that is referenced by the static instance, will not be GC'ed"-これには情報源がありますか?それは意味がなく、他の場所で読んだものと矛盾します。AppPoolがリサイクルされると、関連するApp Domainは完全に破棄され、GCされます。これが発生すると、ルート(AppDomain)がなくなったため、関連する静的インスタンスもGCされます。プールのリサイクルの一環として、新しいAppDomainが作成され、それに関連付けられた静的インスタンスが初期化されます。
ニック

30

静的メンバーには現在のワーカープロセスのスコープのみがあるため、異なるリクエストは同じワーカープロセスで処理される場合とされない場合があるため、リクエストには関係ありません。

  • 特定のユーザーとリクエスト間でデータを共有するには、HttpContext.Current.Sessionを使用します。
  • 特定のリクエスト内でデータを共有するには、HttpContext.Current.Itemsを使用します。
  • アプリケーション全体でデータを共有するには、そのためのメカニズムを作成するか、IISを構成して単一のプロセスで動作し、シングルトンを作成してアプリケーションを使用します。

ちなみに、ワーカープロセスの既定の数は1なので、静的メンバーにはアプリケーション全体のスコープがあると考える人でWebがいっぱいになっているのはこのためです。


11

タイプはアプリドメインに含まれているので、アプリドメインがリサイクルされない限り、またはリクエストが別のアプリドメインによって提供される場合は、静的クラスが存在することを期待します。

特定のリクエストに固有のオブジェクトを作成するいくつかの方法を考えることができます。たとえば、オブジェクトをApplication.BeginRequestでインスタンス化し、HttpRequestオブジェクトに格納して、すべてのオブジェクトからアクセスできるようにすることができます。リクエスト処理パイプライン。


4

それらが各要求に固有ではない場合、それらを許可する方法はありますか?

いいえ。静的メンバーはASP.NETプロセスによって所有され、Webアプリのすべてのユーザーによって共有されます。セッション変数などの他のセッション管理手法に目を向ける必要があります。


1

通常、静的メソッド、プロパティ、クラスはApplicationレベルで共通です。アプリケーションが存続している限り、それらは共有されます。

ThreadStatic属性を使用して、異なる動作を指定できます。その場合、それらは現在のスレッドに固有であり、それは各要求に固有であると思います。
あまりにも複雑に見えるので、私はこれを勧めません。

を使用HttpContext.Current.Itemsして、1つのリクエストにHttpContext.Current.Sessionスタッフを設定したり、(リクエスト全体で)1人のユーザーにスタッフを設定したりできます。

ただし、一般に、のようなものを使用する必要がない限りServer.Transfer、最善の方法は基本的に一度作成してから、メソッド呼び出しを介して明示的に渡すことです。


3
Jon Skeetは、ThreadStaticがASP.Netで安全であることは決してないことを示しています。stackoverflow.com/questions/4791208/
Mark Lindell

スレッドはリクエストに固有ではないため、反対票が投じられました。この回答を削除してください
ビスケット2017年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.