Являются ли статические объекты уникальными для каждого пользователя?

У меня есть приложение .net (С#), которое выглядит примерно так

public partial class _Default : System.Web.UI.Page
{
    #region initial variables setup

    private static exam theExam;

    #endregion


    protected void Page_Load(object sender, EventArgs e)
    {
       if(!IsPostBack)
       {
        string userid = Request.Querystring["user"].ToString();
           theExam = new exam(userid, "some values");
       }
    }
// rest of code.

Теперь мой вопрос: если пользователь 105 регистрируется в экземпляре экзамена, экзамен создается и назначается статической декларации сверху. Если затем пользователь 204 войдет в систему с другого компьютера, получит ли статический объект вверху значение 204 даже на компьютере пользователя 105?


person Migs    schedule 23.09.2010    source источник


Ответы (5)


Нет, статический объект является одним и тем же экземпляром для всех, кто вошёл в систему. Кроме того, объект находится не на компьютере 105, а, конечно, только на веб-сервере.

person Sander Rijken    schedule 23.09.2010
comment
Для пояснения: Статика уникальна для домена приложения, и в этом случае это все веб-приложение. Примечание. Если вы используете балансировку нагрузки, они не уникальны для двух и более серверов. Так что имейте это в виду для горизонтального масштабирования. - person Aren; 24.09.2010
comment
Если вы используете [ThreadStaticAttribute], каждый поток будет иметь собственный экземпляр этой статической переменной. - person Bear Monkey; 24.09.2010
comment
Действительно, но потоки повторно используются для разных запросов, так что этого недостаточно. Использование сеанса - лучший способ для чего-то подобного. - person Sander Rijken; 24.09.2010
comment
Конечно. Сессия - это то, что следует использовать. Использование статических переменных в ASP.NET — плохая идея. Я отвечал Арену, в основном комментируя, что статика не обязательно уникальна только для домена приложения. - person Bear Monkey; 24.09.2010

Время жизни статических переменных и пользовательских сессий — это очень разные понятия. Статические переменные имеют время жизни, определенное CLR, и по существу сводятся к следующим двум правилам.

  1. Существует одно место хранения для статической переменной на AppDomain
  2. Каждое уникальное создание универсального типа создает другую статическую переменную.

Мне трудно написать второе правило, не будучи двусмысленным в отношении уникального. По сути, MyType<int> и MyType<string> имеют разные статические переменные. В то время как MyType<int> и MyType<int> используют один и тот же.

Доступ пользователя к веб-серверу не влияет ни на один из них.

Если вы хотите иметь данные для каждого пользователя, используйте Session для хранения данных.

Session["examKey"] = theExam;
person JaredPar    schedule 23.09.2010
comment
Я не уверен, правильно ли я это делаю, но в основном то, что я сделал, это экзамен newExam = новый экзамен (значение, значение); Session[someKey] = newExam, затем я просто привожу Session[someKey] как exam theExam = (exam) Session[someKey], чтобы я мог получить объекты... это правильный способ сделать это? - person Migs; 24.09.2010

Краткий ответ: да, статическое поле является глобальным для AppDomain, поэтому выполнение этого для одного пользователя приведет к изменению данных для другого пользователя.

Вы, вероятно, захотите вместо этого изучить использование хранилища сеансов, которое ограничено для каждого пользователя, например.

var theExam = Session["exam"] as Exam;
person flatline    schedule 23.09.2010

Для каждого AppDomain существует один «экземпляр» статического объекта. Так что ответ на ваш вопрос - да. Поскольку вы перезаписываете переменную при входе пользователя 204, такое же значение будет отображаться и для пользователя 105.

Некоторые общие советы

  • По возможности избегайте статических полей
  • Используйте сеанс для хранения временной информации в контексте сеанса просмотра пользователем
    Session["exam"] = currentUser.Exam;
  • Используйте поставщика профилей для сохранения информации о каждом пользователе между сеансами.
person Venemo    schedule 23.09.2010
comment
Я думаю, что говорить о том, чтобы избегать статических полей, где это возможно, немного переусердствовать. Я видел людей, которые буквально боятся их использовать, потому что они не понимают, как они работают, и кто-то сказал им, что они могут все испортить. Нет ничего плохого в том, чтобы использовать их и сделать многие вещи намного проще (вспомогательные методы, кэширование в памяти). Просто нужно уметь их правильно использовать. - person Matti Virkkunen; 24.09.2010
comment
@Matti - метод не является полем. Нет ничего плохого во вспомогательных методах. Вам просто нужно знать, как правильно их использовать - Согласен! :) - person Venemo; 24.09.2010
comment
Я видел людей, которые боятся всего ключевого слова static :I - person Matti Virkkunen; 24.09.2010
comment
@Matti - Я тоже, но больше в контексте C/C++, чем C# - person Venemo; 24.09.2010

В .Net также есть атрибут [ThreadStatic], который создает один статический экземпляр для каждого потока.

http://msdn.microsoft.com/en-us/library/system.threadstaticattribute(VS.71).aspx

person Steven    schedule 23.09.2010
comment
Хорошо, что вы это упомянули, но в данном случае это тоже было бы плохо, так как потоки повторно используются в пуле потоков ASP.NET. - person Sander Rijken; 24.09.2010
comment
Однако поток не предназначен для каждого пользователя. Ни один запрос не гарантированно останется в одном и том же потоке от начала до конца. Таким образом, threadstatics в основном (если не полностью) бесполезен в веб-приложениях. - person Guffa; 24.09.2010