Apakah instance kelas statis unik untuk permintaan atau server di ASP.NET?

182

Di situs web ASP.NET, apakah kelas statis unik untuk setiap permintaan web, atau mereka dipakai setiap kali diperlukan dan GCed setiap kali GC memutuskan untuk membuangnya?

Alasan saya bertanya adalah karena saya telah menulis beberapa kelas statis sebelumnya di C # dan tingkah lakunya berbeda dari yang saya harapkan. Saya akan mengharapkan kelas statis menjadi unik untuk setiap permintaan, tetapi sepertinya bukan itu masalahnya.

Jika mereka tidak unik untuk setiap permintaan, apakah ada cara untuk memungkinkannya?

UPDATE:
Jawaban yang diberikan oleh driis tepat seperti yang saya butuhkan. Saya sudah menggunakan kelas singleton, namun menggunakan contoh statis dan karenanya dibagikan di antara permintaan bahkan jika pengguna berbeda yang dalam hal ini adalah hal yang buruk. Menggunakan HttpContext.Current.Itemsmemecahkan masalah saya dengan sempurna. Bagi siapa saja yang menemukan pertanyaan ini di masa depan, ini adalah implementasi saya, disederhanakan dan dipersingkat sehingga mudah untuk memahami polanya:

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;
        }
    }
}
Dan Herbert
sumber
Hanya kepala: Jika Anda mengarahkan permintaan Anda, katakanlah, dengan filterContext.Result = new RedirectResult(...)Anda akan kehilangan item Anda karena HttpContext baru akan dibuat. Lebih detail di sini: stackoverflow.com/questions/16697601/…
Reuel Ribeiro
Pertanyaan terkait dengan jawaban yang baik ada di stackoverflow.com/q/5219431 .
Theophilus

Jawaban:

146

Kelas statis dan bidang instance statis Anda dibagikan di antara semua permintaan ke aplikasi, dan memiliki masa pakai yang sama dengan domain aplikasi. Karena itu, Anda harus berhati-hati saat menggunakan instance statis, karena Anda mungkin memiliki masalah sinkronisasi dan sejenisnya. Juga ingat, bahwa instance statis tidak akan GC'ed sebelum kumpulan aplikasi didaur ulang, dan oleh karena itu segala sesuatu yang dirujuk oleh instance statis, tidak akan GC'ed. Ini dapat menyebabkan masalah penggunaan memori.

Jika Anda membutuhkan contoh dengan masa hidup yang sama dengan permintaan, saya akan menyarankan untuk menggunakan HttpContext.Current.Itemskoleksi. Ini dengan desain dimaksudkan untuk menjadi tempat untuk menyimpan barang-barang yang Anda butuhkan sepanjang permintaan. Untuk desain dan keterbacaan yang lebih baik, Anda dapat menggunakan pola Singleton untuk membantu Anda mengelola barang-barang ini. Cukup buat kelas Singleton yang menyimpan instansinya di HttpContext.Current.Items. (Di perpustakaan umum saya untuk ASP.NET, saya memiliki kelas SingletonRequest generik untuk tujuan ini).

driis
sumber
3
Bisakah Anda memberikan contoh pola Singleton Anda yang melibatkan HttpContext.Current.Items?
Airn5475
Lebih detail tentang situasi saya: di aplikasi web saya, pengguna akan berjalan melalui perpustakaan kelas kode yang menggunakan properti kelas bersama. Saya ingin properti ini khusus untuk pengguna, tetapi saya tidak ingin menyerahkan properti ini ke berbagai fungsi. Bisakah desain yang Anda sebutkan, menangani ini dengan benar?
Airn5475
Tolong, bisakah Anda membagikan kelas SingletonRequest?
Tebo
Saya tidak menyimpan data apa pun di kelas statis. Saya menggunakan kelas statis hanya untuk mendapatkan data atau mengatur data sebagai lapisan data. Jadi, apakah ada masalah?
hiasi
"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"- Apakah ada sumber untuk ini, karena tidak masuk akal dan bertentangan dengan apa yang saya baca di tempat lain. Ketika AppPool didaur ulang, Domain Aplikasi terkait sepenuhnya dihancurkan dan GC'd. Ketika ini terjadi, setiap instance statis terkait juga akan menjadi GC karena root (AppDomain) hilang. Sebagai bagian dari kumpulan daur ulang, AppDomain baru dibuat dan itu terkait dengan contoh statis diinisialisasi.
Nick
30

Anggota statis memiliki ruang lingkup proses pekerja saat ini saja, sehingga tidak ada hubungannya dengan permintaan, karena permintaan yang berbeda mungkin atau mungkin tidak ditangani oleh proses pekerja yang sama.

  • Untuk berbagi data dengan pengguna tertentu dan seluruh permintaan, gunakan HttpContext.Current.Session.
  • Untuk berbagi data dalam permintaan tertentu, gunakan HttpContext.Current.Items.
  • Untuk berbagi data di seluruh aplikasi, baik menulis mekanisme untuk itu, atau mengkonfigurasi IIS untuk bekerja dengan satu proses dan menulis Aplikasi singleton / gunakan.

Ngomong-ngomong, jumlah standar proses pekerja adalah 1, jadi ini sebabnya web penuh dengan orang yang berpikir bahwa anggota statis memiliki cakupan seluruh aplikasi.

Moshe Bixenshpaner
sumber
11

Karena jenisnya terdapat dalam domain aplikasi, saya berharap kelas statis akan ada selama domain aplikasi tidak didaur ulang, atau jika permintaan dilayani oleh domain aplikasi yang berbeda.

Saya dapat memikirkan beberapa cara untuk membuat objek spesifik untuk permintaan tertentu tergantung pada apa yang ingin Anda lakukan, misalnya Anda dapat membuat instance objek di Application.BeginRequest dan kemudian menyimpannya di objek HttpRequest sehingga dapat diakses oleh semua objek di pipa pemrosesan permintaan.

Sijin
sumber
4

Jika mereka tidak unik untuk setiap permintaan, apakah ada cara untuk memungkinkannya?

Nggak. Anggota statis dimiliki oleh proses ASP.NET dan dibagikan oleh semua pengguna aplikasi Web. Anda harus beralih ke teknik manajemen sesi lain seperti variabel sesi.

rp.
sumber
1

Biasanya metode statis, properti, dan kelas umum di Applicationlevel. Selama aplikasi hidup, mereka dibagikan.

Anda dapat menentukan perilaku yang berbeda dengan menggunakan ThreadStaticatribut. Dalam hal ini mereka akan spesifik untuk utas saat ini, yang, saya pikir, khusus untuk setiap permintaan.
Saya tidak akan menyarankan ini karena tampaknya rumit.

Anda dapat menggunakan HttpContext.Current.Itemsuntuk mengatur barang untuk satu permintaan, atau HttpContext.Current.Sessionuntuk mengatur barang untuk satu pengguna (seluruh permintaan).

Secara umum, kecuali Anda harus menggunakan hal-hal seperti Server.Transfer, cara terbaik pada dasarnya adalah menciptakan sesuatu sekali dan kemudian mengirimkannya secara eksplisit melalui pemanggilan metode.

Sklivvz
sumber
3
Jon Skeet menunjukkan kepada kita bahwa ThreadStatic tidak pernah aman di ASP.Net stackoverflow.com/questions/4791208/…
Mark Lindell
Pilihan turun karena utas tidak unik untuk permintaan. Tolong, hapus Jawaban ini
seebiscuit