Czy w witrynie ASP.NET klasy statyczne są unikalne dla każdego żądania WWW, czy też są tworzone w razie potrzeby, a GCed za każdym razem, gdy GC zdecyduje się je usunąć?
Powodem, dla którego pytam, jest to, że napisałem już kilka klas statycznych w języku C #, a zachowanie jest inne niż się spodziewałem. Spodziewałbym się, że klasy statyczne będą unikalne dla każdego żądania, ale tak nie jest.
Jeśli nie są one unikalne dla każdego żądania, czy istnieje sposób, aby im to umożliwić?
AKTUALIZACJA:
Driis odpowiedział mi dokładnie to, czego potrzebowałem. Korzystałem już z klasy singleton, jednak korzystałem z instancji statycznej i dlatego byłem współdzielony między żądaniami, nawet jeśli użytkownicy byli różni, co w tym przypadku było złe. Używanie HttpContext.Current.Items
doskonale rozwiązuje mój problem. Dla każdego, kto natknie się na to pytanie w przyszłości, oto moja implementacja, uproszczona i skrócona, aby łatwo zrozumieć wzór:
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(...)
stracisz swoje przedmioty, ponieważ zostanie utworzony nowy HttpContext. Więcej szczegółów tutaj: stackoverflow.com/questions/16697601/…Odpowiedzi:
Twoje klasy statyczne i pola instancji statycznych są współużytkowane między wszystkimi żądaniami do aplikacji i mają taki sam okres istnienia jak domena aplikacji. Dlatego należy zachować ostrożność podczas korzystania z instancji statycznych, ponieważ mogą występować problemy z synchronizacją itp. Należy również pamiętać, że wystąpienia statyczne nie zostaną poddane GC przed ponownym przetworzeniem puli aplikacji, a zatem wszystko, do czego odnosi się wystąpienie statyczne, nie zostanie poddane GC. Może to prowadzić do problemów z użyciem pamięci.
Jeśli potrzebujesz instancji o takim samym okresie istnienia jak żądanie, sugerowałbym użycie
HttpContext.Current.Items
kolekcji. To z założenia ma być miejscem do przechowywania rzeczy potrzebnych w wyniku żądania. Aby uzyskać lepszy wygląd i czytelność, możesz użyć wzorca Singleton, aby pomóc Ci zarządzać tymi elementami. Wystarczy utworzyć klasę Singleton, w której będzie przechowywana jej instancjaHttpContext.Current.Items
. (W mojej wspólnej bibliotece dla ASP.NET mam do tego celu ogólną klasę SingletonRequest).źródło
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"
- Czy jest na to jakieś źródło, ponieważ nie ma to żadnego sensu i jest sprzeczne z tym, co przeczytałem gdzie indziej. Po ponownym przetworzeniu AppPool powiązana domena aplikacji zostaje całkowicie zburzona i poddana GC. Kiedy tak się stanie, wszelkie powiązane instancje statyczne również zostaną GC, ponieważ ich root (AppDomain) zniknął. W ramach recyklingu puli tworzona jest nowa AppDomain i inicjowane są powiązane z nią instancje statyczne.Członkowie statyczni mają zakres tylko bieżącego procesu roboczego, więc nie ma to nic wspólnego z żądaniami, ponieważ różne żądania mogą, ale nie muszą być obsługiwane przez ten sam proces roboczy.
Nawiasem mówiąc, domyślna liczba procesów roboczych wynosi 1, dlatego sieć jest pełna ludzi myślących, że członkowie statyczni mają zasięg całej aplikacji.
źródło
Ponieważ typy są zawarte w domenie aplikacji, oczekiwałbym, że będą istnieć klasy statyczne, dopóki domena aplikacji nie zostanie przetworzona lub jeśli żądanie zostanie obsłużone przez inną domenę aplikacji.
Mogę wymyślić kilka sposobów, aby obiekty specyficzne dla konkretnego żądania zależały od tego, co chcesz zrobić, na przykład możesz utworzyć instancję obiektu w Application.BeginRequest, a następnie zapisać go w obiekcie HttpRequest, aby był dostępny dla wszystkich obiektów w potok przetwarzania żądania.
źródło
Nie. Członkowie statyczni są własnością procesu ASP.NET i są współużytkowani przez wszystkich użytkowników aplikacji sieci Web. Musisz przejść do innych technik zarządzania sesjami, takich jak zmienne sesji.
źródło
Normalnie statyczne metody, właściwości i klasy są wspólne na
Application
poziomie. Tak długo, jak aplikacja działa, są udostępniane.Możesz określić inne zachowanie za pomocą
ThreadStatic
atrybutu. W takim przypadku będą one specyficzne dla bieżącego wątku, który moim zdaniem jest specyficzny dla każdego żądania.Nie radziłbym tego jednak, ponieważ wydaje się to zbyt skomplikowane.
Możesz użyć
HttpContext.Current.Items
do skonfigurowania rzeczy dla jednego żądania lubHttpContext.Current.Session
do skonfigurowania rzeczy dla jednego użytkownika (między żądaniami).Zasadniczo jednak, chyba że musisz używać takich rzeczy
Server.Transfer
, najlepszym sposobem jest po prostu utworzenie rzeczy raz, a następnie jawne przekazanie ich przez wywołanie metody.źródło