Em um site ASP.NET, as classes estáticas são exclusivas para cada solicitação da Web ou são instanciadas sempre que necessário e submetidas ao GC sempre que o GC decide descartá-las?
A razão pela qual pergunto é porque escrevi algumas classes estáticas antes em C # e o comportamento é diferente do que eu esperava. Eu esperava que as classes estáticas fossem exclusivas para cada solicitação, mas não parece ser esse o caso.
Se eles não são exclusivos para cada solicitação, existe uma maneira de permitir que eles sejam?
ATUALIZAÇÃO:
A resposta que driis me deu foi exatamente o que eu precisava. Eu já estava usando uma classe singleton, no entanto, estava usando uma instância estática e, portanto, estava sendo compartilhada entre solicitações, mesmo que os usuários fossem diferentes, o que, nesse caso, era uma coisa ruim. Usar HttpContext.Current.Items
resolve meu problema perfeitamente. Para quem se deparar com essa questão no futuro, aqui está minha implementação, simplificada e abreviada para facilitar a compreensão do padrão:
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;
}
}
}
filterContext.Result = new RedirectResult(...)
você perderá seus itens porque um novo HttpContext será criado. Mais detalhes aqui: stackoverflow.com/questions/16697601/…Respostas:
Suas classes estáticas e campos de instância estática são compartilhados entre todas as solicitações ao aplicativo e têm a mesma vida útil do domínio do aplicativo. Portanto, você deve ter cuidado ao usar instâncias estáticas, pois você pode ter problemas de sincronização e similares. Lembre-se também de que instâncias estáticas não serão submetidas ao GC antes que o pool de aplicativos seja reciclado e, portanto, tudo o que for referenciado pela instância estática não será submetido ao GC. Isso pode levar a problemas de uso de memória.
Se você precisar de uma instância com a mesma duração de uma solicitação, sugiro usar a
HttpContext.Current.Items
coleção. Esse design foi concebido para ser um local para armazenar coisas de que você precisa durante a solicitação. Para melhor design e legibilidade, você pode usar o padrão Singleton para ajudá-lo a gerenciar esses itens. Basta criar uma classe Singleton que armazene sua instância noHttpContext.Current.Items
. (Na minha biblioteca comum do ASP.NET, tenho uma classe SingletonRequest genérica para esse fim).fonte
HttpContext.Current.Items
?"static instances will not be GC'ed before the application pool is recycled, and therefore everything that is referenced by the static instance, will not be GC'ed"
- Existe alguma fonte para isso, porque não faz sentido e entra em conflito com o que li em outro lugar. Quando o AppPool é reciclado, o Domínio do Aplicativo relacionado é completamente destruído e armazenado em GC. Quando isso acontece, qualquer instância estática relacionada também será submetida ao GC porque sua raiz (o AppDomain) desapareceu. Como parte da reciclagem do pool, um novo AppDomain é criado e suas instâncias estáticas associadas são inicializadas.Os membros estáticos têm apenas um escopo do processo de trabalho atual, portanto, nada tem a ver com solicitações, porque solicitações diferentes podem ou não ser tratadas pelo mesmo processo de trabalho.
A propósito, o número padrão de processos de trabalho é 1; é por isso que a web está cheia de pessoas pensando que membros estáticos têm um escopo de todo o aplicativo.
fonte
Como os tipos estão contidos em um domínio de aplicativo, seria de esperar que as classes estáticas estivessem presentes desde que o domínio do aplicativo não fosse reciclado ou se a solicitação fosse atendida por um domínio de aplicativo diferente.
Posso pensar em várias maneiras de tornar objetos específicos para uma solicitação específica, dependendo do que você deseja fazer, por exemplo, você pode instanciar o objeto em Application.BeginRequest e armazená-lo no objeto HttpRequest para que ele possa ser acessado por todos os objetos em o pipeline de processamento de solicitações.
fonte
Não. Os membros estáticos pertencem ao processo ASP.NET e são compartilhados por todos os usuários do aplicativo Web. Você precisará recorrer a outras técnicas de gerenciamento de sessões, como variáveis de sessão.
fonte
Métodos, propriedades e classes normalmente estáticos são comuns no
Application
nível. Enquanto o aplicativo permanecer, eles serão compartilhados.Você pode especificar um comportamento diferente usando o
ThreadStatic
atributo Nesse caso, eles serão específicos para o segmento atual, que, eu acho, é específico para cada solicitação.Eu não recomendaria isso, embora pareça complicado demais.
Você pode usar
HttpContext.Current.Items
para configurar itens para uma solicitação ouHttpContext.Current.Session
para um usuário (entre solicitações).Em geral, porém, a menos que você precise usar coisas como
Server.Transfer
, a melhor maneira é basicamente criar coisas uma vez e depois transmiti-las explicitamente via invocação de método.fonte