Statik sınıf örnekleri ASP.NET'teki bir istek veya sunucu için benzersiz mi?


182

Bir ASP.NET web sitesinde, statik sınıflar her web isteğine özgüdür veya gerektiğinde somutlaştırılır ve GC bunları atmaya karar verdiğinde GC'lenir mi?

Sormamın nedeni, daha önce C # 'da bazı statik sınıflar yazdım ve davranış beklediğimden farklı. Statik sınıfların her istek için benzersiz olmasını beklerdim, ama durum böyle görünmüyor.

Her bir istek için benzersiz değilse, bu isteklere izin vermenin bir yolu var mı?

GÜNCELLEME:
Bana verilen cevap tam olarak ihtiyacım olan şeydi. Zaten tek bir sınıf kullanıyordum, ancak statik bir örnek kullanıyordu ve bu nedenle, bu durumda kötü bir şey olan kullanıcılar farklı olsa bile istekler arasında paylaşılıyordu. Kullanımı HttpContext.Current.Itemsproblemimi mükemmel bir şekilde çözer. Gelecekte bu soru üzerine tökezleyen herkes için, benim deseni, anlaşılması kolay olacak şekilde basitleştirilmiş ve kısaltılmış benim uygulama:

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

Sadece bir uyarı: Eğer isteğinizi yeniden yönlendirirseniz, filterContext.Result = new RedirectResult(...)yeni bir HttpContext oluşturulacağı için öğelerinizi kaybedersiniz. Daha fazla ayrıntı için: stackoverflow.com/questions/16697601/…
Reuel Ribeiro

İyi bir yanıtı olan ilgili bir soru stackoverflow.com/q/5219431 adresindedir .
Theophilus

Yanıtlar:


146

Statik sınıflarınız ve statik örnek alanlarınız, uygulamaya yapılan tüm istekler arasında paylaşılır ve uygulama etki alanıyla aynı kullanım ömrüne sahiptir. Bu nedenle, senkronizasyon sorunları ve benzerleriniz olabileceğinden statik örnekleri kullanırken dikkatli olmalısınız. Ayrıca, uygulama havuzu geri dönüştürülmeden önce statik örneklerin GC'lenmeyeceğini ve bu nedenle statik örnek tarafından başvurulan her şeyin GC'lenmeyeceğini unutmayın. Bu, bellek kullanım sorunlarına yol açabilir.

İstekle aynı kullanım ömrüne sahip bir örneğe ihtiyacınız varsa, HttpContext.Current.Itemskoleksiyonu kullanmanızı öneririm . Bu, tasarım gereği, istek üzerine ihtiyacınız olan şeyleri depolamak için bir yer olması anlamına gelir. Daha güzel tasarım ve okunabilirlik için, bu öğeleri yönetmenize yardımcı olması amacıyla Singleton desenini kullanabilirsiniz. Sadece örneğini saklayan bir Singleton sınıfı oluşturun HttpContext.Current.Items. (ASP.NET için ortak kütüphanemde, bu amaçla genel bir SingletonRequest sınıfım var).


3
Tekli kalıbınızla ilgili bir örnek verebilir misiniz HttpContext.Current.Items?
Airn5475

Durumum hakkında daha fazla ayrıntı: Web uygulamamda kullanıcı, paylaşılan bir sınıf özelliği kullanan bir kod sınıf kitaplığıyla çalışır. Bu özelliğin kullanıcıya özgü olmasını istiyorum, ancak bu özelliği farklı işlevlere teslim etmek istemiyorum. Bahsettiğiniz tasarım bunu doğru bir şekilde halledebilir mi?
Airn5475

Lütfen, SingletonRequest sınıfını paylaşabilir misiniz?
Tebo

Statik sınıfta veri depolamıyorum. Statik sınıfı yalnızca veri almak veya veri katmanı olarak veri ayarlamak için kullanıyorum. Yani herhangi bir sorun var mı?
cafcaflı

"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"- Bunun için herhangi bir kaynak var mı, çünkü başka bir yerde okuduğum şeyle bir anlam ifade etmiyor ve çelişiyor. AppPool geri dönüştürüldüğünde, ilgili Uygulama Alanı tamamen yırtılır ve GC olur. Bu durumda, kökleri (AppDomain) gittiği için ilgili statik örnekler de GC'd olur. Havuz geri dönüşümünün bir parçası olarak yeni bir AppDomain oluşturulur ve ilişkilendirilmiş statik örnekleri başlatılır.
Nick

30

Statik üyelerin yalnızca geçerli çalışan sürecinin bir kapsamı vardır, bu nedenle farklı çalışanlar aynı çalışan süreç tarafından işlenebileceği veya işlenemeyebileceğinden, isteklerle ilgisi yoktur.

  • Verileri belirli bir kullanıcıyla ve talepler arasında paylaşmak için HttpContext.Current.Session kullanın.
  • Verileri belirli bir istek içinde paylaşmak için HttpContext.Current.Items öğesini kullanın.
  • Tüm uygulama boyunca veri paylaşmak için, bunun için bir mekanizma yazın veya IIS'yi tek bir işlemle çalışacak şekilde yapılandırın ve tek bir / yazma Uygulaması yazın.

Bu arada, varsayılan çalışan süreç sayısı 1'dir, bu yüzden web, statik üyelerin tüm uygulamanın kapsamına sahip olduğunu düşünen insanlarla doludur.


11

Türler bir uygulama etki alanında bulunduğundan, uygulama etki alanı geri dönüştürülmediği sürece veya istek farklı bir uygulama etki alanı tarafından sunuluyorsa statik sınıfların mevcut olmasını beklerim.

Belirli bir isteğe özgü nesneleri yapmak için çeşitli yollar düşünebilirsiniz ne yapmak istediğinize bağlıdır, örneğin Application.BeginRequest nesnesini örneklemek ve daha sonra tüm nesneler tarafından erişilebilir böylece HttpRequest nesnesinde depolamak istek işleme boru hattı.


4

Her bir istek için benzersiz değilse, bu isteklere izin vermenin bir yolu var mı?

Hayır! Statik üyelerin sahibi ASP.NET işlemidir ve Web uygulamasının tüm kullanıcıları tarafından paylaşılır . Oturum değişkenleri gibi diğer oturum yönetimi tekniklerine başvurmanız gerekir.


1

Normalde statik yöntemler, özellikler ve sınıflar Applicationdüzeyde ortaktır . Uygulama yaşadığı sürece paylaşılır.

ThreadStaticÖzelliği kullanarak farklı bir davranış belirtebilirsiniz . Bu durumda, geçerli iş parçacığına özgü olacaklar, bence her istek için özel.
Ben aşırı karmaşık görünüyor olsa ben bunu tavsiye etmem.

Sen kullanabilirsiniz HttpContext.Current.Itemsbir istek için ayarlanan şeyler kadar, ya da HttpContext.Current.Session(istekleri karşısında) bir kullanıcı için yukarı ayarlanmış şeyler.

Genel olarak, böyle şeyleri kullanmanız gerekmedikçe Server.Transfer, en iyi yol temelde bir kez bir şeyler yaratmak ve daha sonra bunları yöntem çağırma yoluyla açıkça geçirmektir.


3
Jon Skeet, ASP.Net'te ThreadStatic'in asla güvenli olmadığını bize gösteriyor stackoverflow.com/questions/4791208/…
Mark Lindell

Bir iş parçacığı bir istek için benzersiz olmadığından aşağı oy kullanıldı. Lütfen, bu cevabı kaldırın
seebiscuit
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.