18

ASP.NETのアプリケーション状態の代わりに静的変数を使用するように計画していますが、これが正しいアプローチかどうか疑問に思っています。

[Global.asax.cs]

...

public class Global : System.Web.HttpApplication
{
    void Application_Start(object sender, EventArgs e)
    {
        // Code that runs on application startup

    }

    ...

    private static Dictionary<string, object> cacheItems = new Dictionary<string, object>();
    private static object locker = new object();

    public static Dictionary<string, object> CacheItems
    {
        get
        {
            lock (locker)
            {
                return cacheItems;
            }
        }

        set
        {
            lock (locker)
            {
                cacheItems = value;
            }
        }
    }

    public static void RemoveCacheItem(string key)
    {
        cacheItems.Remove(key);
    }

    ...
}

ご覧のとおり、自動的に作成されたGlobal.asax(およびコードビハインド)ファイルを使用しています。いくつかの静的変数とメソッドを追加しました。私はこのように後でそれらを使用することができます:

[some .cs file]
foreach(KeyValuePair<string, object> dictItem in Global.CacheItems)
{
    ...

これは正しい方法ですか、それとも既存のグローバルの代わりに新しいクラスを作成する必要がありますか?新しいクラスを作成する必要がある場合、どのように、どこでそれを行うことができますか?

4

1 に答える 1

20

マイクロソフトの言うこと

ASP.NETには、主に従来のASPとの互換性のためにアプリケーションの状態が含まれているため、既存のアプリケーションをASP.NETに簡単に移行できます。Applicationオブジェクトではなく、アプリケーションクラスの静的メンバーにデータを格納することをお勧めします。これにより、アプリケーションディクショナリの項目にアクセスするよりも速く静的変数にアクセスできるため、パフォーマンスが向上します。

参照:http ://support.microsoft.com/default.aspx?scid = kb; en-us; Q312607

私の経験

静的変数とアプリケーション状態の主な違いは、アプリケーション状態はすべてのスレッドとプールで同じですが、静的変数はプールごとにのみ同じであるということです。

新しいテストの結果、アプリケーションの状態変数は静的変数と同じであり、アプリケーションの静的変数を参照しているだけであり、Microsoftが言うように互換性の理由で存在していることがわかりました。

サイト(Webガーデン)を実行しているプールが4つある場合は、4セットの異なる静的メモリがあります。

あなたのコード

コードについては、辞書データにアクセスする方法にバグがあり、実際のWebではエラーが発生します。コードのこの部分は、完全な辞書の変数をロックしますが、それを使用するときに行う変更はロックしません。

// this is not enough to manipulate your data !
public static Dictionary<string, object> CacheItems
{
    get { lock (locker) { return cacheItems; } }
    set { lock (locker) { cacheItems = value; } }
}

正しいアプローチは、たとえば、完了するまで追加/削除のすべてのアクションをロックすることです。

private static Dictionary<string, object> cacheItems = new Dictionary<string, object>();
private static object locker = new object();
public Dictionary<string, object> CacheItems
{
    get{ return cacheItems; }
    set{ cacheItems = value; }
}

SomeFunction()
{
    ...
    lock(locker)
    {
        CacheItems["VariableName"] = SomeObject;
    }
    ...
}

一方、アプリケーションの状態でデータを操作する場合は、そのグローバルロックを使用する必要がApplication.Lock();ありApplication.UnLock();ます。

Application.Lock();
Application["PageRequestCount"] = ((int)Application["PageRequestCount"]) + 1;
Application.UnLock();

いくつかの結論で締めくくります:

アプリケーションの状態を避け、コードで静的変数を使用するだけです。

于 2012-06-09T19:42:55.610 に答える