2008-10-12 6 views
155

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

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

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

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; 
     } 
    } 
} 
+0

Просто голова: если вы перенаправляете свой запрос, скажем, с помощью `filterContext.Result = new RedirectResult (...)`, вы потеряете свои элементы, потому что будет создан новый HttpContext. Подробнее здесь: https://stackoverflow.com/questions/16697601/response-redirect-does-not-preserve-httpcontext-current-items – 2018-03-01 18:22:30

ответ

119

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

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

+2

Не могли бы вы предоставить образец вашего шаблона Singleton с использованием `HttpContext.Current.Items`? – Airn5475 2011-08-25 20:23:38

+0

Подробнее о моей ситуации: в моем веб-приложении пользователь будет проходить через библиотеку классов кода, которая использует свойство shared class. Я хочу, чтобы это свойство было специфичным для пользователя, но я не хочу прикладывать это свойство к различным функциям. Может ли дизайн, который вы упомянули, справиться с этим правильно? – Airn5475 2011-08-25 20:40:59

11

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

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

4

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

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

0

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

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

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

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

16

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

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

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

 Смежные вопросы

  • Нет связанных вопросов^_^