Являются ли экземпляры статического класса уникальными для запроса или сервера в ASP.NET? - PullRequest
173 голосов
/ 12 октября 2008

Являются ли статические классы уникальными для каждого веб-запроса на веб-сайте ASP.NET или они создаются при необходимости и GCed всякий раз, когда GC решает их удалить?

Причина, по которой я спрашиваю, состоит в том, что я ранее написал несколько статических классов на C #, и поведение отличается от того, что я ожидал. Я ожидал, что статические классы будут уникальными для каждого запроса, но, похоже, это не так.

Если они не уникальны для каждого запроса, есть ли способ разрешить их отображение?

UPDATE:
Ответ, который дриса дала мне, был именно тем, что мне было нужно. Я уже использовал одноэлементный класс, однако он использовал статический экземпляр и поэтому распределялся между запросами, даже если пользователи были разными, что в данном случае было плохо. Использование 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;
        }
    }
}

Ответы [ 5 ]

140 голосов
/ 12 октября 2008

Ваши статические классы и поля статических экземпляров совместно используются всеми запросами к приложению и имеют то же время жизни, что и домен приложения. Поэтому вы должны быть осторожны при использовании статических экземпляров, поскольку у вас могут возникнуть проблемы с синхронизацией и тому подобное. Также имейте в виду, что статические экземпляры не будут подвергаться GC-обработке до повторного использования пула приложений, и поэтому все, на что ссылается статический экземпляр, не будет GC-обработано. Это может привести к проблемам с использованием памяти.

Если вам нужен экземпляр с тем же временем жизни, что и для запроса, я бы предложил использовать коллекцию HttpContext.Current.Items. Это по замыслу предназначено для хранения вещей, которые вам нужны во время запроса. Для лучшего дизайна и удобочитаемости вы можете использовать шаблон Singleton, чтобы помочь вам управлять этими элементами. Просто создайте класс Singleton, который хранит свой экземпляр в HttpContext.Current.Items. (В моей общей библиотеке для ASP.NET у меня есть универсальный класс SingletonRequest для этой цели).

27 голосов
/ 20 августа 2013

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

  • Для обмена данными с конкретным пользователем и между запросами используйте HttpContext.Current.Session.
  • Для обмена данными в рамках определенного запроса используйте HttpContext.Current.Items.
  • Чтобы обмениваться данными по всему приложению, либо напишите механизм для этого, либо настройте IIS для работы с одним процессом и напишите одно приложение / используйте приложение.

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

11 голосов
/ 12 октября 2008

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

Я могу придумать несколько способов сделать объекты специфичными для конкретного запроса, например, от того, что вы хотите сделать, например, Вы можете создать экземпляр объекта в Application.BeginRequest, а затем сохранить его в объекте HttpRequest, чтобы к нему могли обращаться все объекты в конвейере обработки запросов.

4 голосов
/ 12 октября 2008

Если они не уникальны для каждого запроса, есть ли способ разрешить их отображение?

Нет. Статические члены принадлежат процессу ASP.NET и совместно используются всеми пользователями веб-приложения. Вам нужно будет обратиться к другим методам управления сеансом, таким как переменные сеанса.

0 голосов
/ 12 октября 2008

Обычно статические методы, свойства и классы являются общими на уровне Application. Пока приложение работает, оно является общим.

Вы можете указать другое поведение, используя атрибут ThreadStatic. В этом случае они будут специфичны для текущего потока, который, я думаю, специфичен для каждого запроса.
Я бы не советовал это, хотя это кажется слишком сложным.

Вы можете использовать HttpContext.Current.Items, чтобы настроить вещи для одного запроса, или HttpContext.Current.Session, чтобы настроить вещи для одного пользователя (между запросами).

В общем, хотя, если вам не нужно использовать такие вещи, как Server.Transfer, лучший способ - это просто создать вещи один раз, а затем передать их явно через вызов метода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...