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

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

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

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

UPDATE:
Ответ 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;
        }
    }
}

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Ответ 4

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

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

Ответ 5

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

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

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

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