Вопрос по asp.net, c#, state, static – Использование статических переменных вместо состояния приложения в ASP.NET

16

Я планирую использовать статические переменные вместо состояния приложения в 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)
{
    ...

Это правильный путь, или я должен создать новый класс вместо существующего Global? Если я должен создать новый класс, как я могу это сделать и где?

Ваш Ответ

1   ответ
20
What Microsoft says

classic ASP so that it is easier to migrate existing applications to ASP.NET. It is recommended that you store data in static members of the application class instead of in the Application object. This increases performance because you can access a static variable faster than you can access an item in the Application dictionary.

ссылка :http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312607

My expirience

The main different between static variables and Application state, is that the Application state is the same across all threads and pools, but the static is the same only per pool.

После новых тестов я вижу, что переменные состояния приложения совпадают со статическими переменными, и они просто ссылаются на статическую переменную в приложении, и они просто существуют по причинам совместимости, как говорит Microsoft

Если у вас есть 4 пула, на которых работает ваш сайт (веб-сад), то у вас есть 4 набора различной статической памяти.

Your code

Что касается вашего кода, у вас есть ошибка, связанная с тем, как вы пытаетесь получить доступ к своим словарным данным, и в реальной сети вы будете иметь ошибки. Эта часть кода блокирует переменную полного словаря, но не блокирует изменения, которые вы собираетесь внести при ее использовании.

 // 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;
  }
  ...
}

С другой стороны, когда вы манипулируете данными о состоянии приложения, вам нужно использоватьglobal замок этогоApplication.Lock(); а такжеApplication.UnLock(); например

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

В заключение с некоторыми выводами:

Избегайте состояния приложения и просто используйте статические переменные в своем коде.

Спасибо за ваш ответ. Но мне нужны некоторые разъяснения, если это возможно. Вы имеете в виду, что я должен сохранять блокировку всего словаря, как это делал я, но должен также дополнительно блокировать определенные элементы в операциях добавления / удаления? tesicg
@tesicg, чтобы уточнить, вы должны сделать ОДНУ блокировку только тогда, когда вы измените / отредактируете / удалите / найдете свой словарь. Так что блокировка у вас как есть должна быть снята - это на самом деле только проверка памяти словаря, не достаточно.
Теперь ясно. Большое спасибо. tesicg
Извините меня. И еще один вопрос, который на самом деле является первоначальным вопросом - могу ли я просто поместить все мои новые статические сотрудники в существующий файл Global.asax.cs, как я это сделал? Или создать новый класс? Если я хочу создать новый класс, где он должен быть? tesicg
@tesicg Статические данные доступны в любом месте программы. Для вас, если вы хотите использовать его в Global.asax, самое простое место для их написания - там, в global.asax. Если вы создаете новый класс, класс ether находится внутри dll, который вы включаете в свою программу, ether помещается в app_code. Если у вас есть данные, и вы хотите использовать их на страницах, лучше создать класс, чтобы вы могли включить ссылку на страницы и одновременно в global.asax и использовать их где угодно.

Похожие вопросы