정적 클래스 인스턴스는 ASP.NET의 요청 또는 서버에 고유합니까?


182

ASP.NET 웹 사이트에서 각 웹 요청에 고유 한 정적 클래스가 있습니까? 아니면 GC가 처리하기로 결정할 때마다 필요할 때마다 인스턴스화되고 GC됩니다.

내가 묻는 이유는 C #에서 정적 클래스를 작성했기 때문에 예상했던 것과 동작이 다르기 때문입니다. 정적 클래스가 각 요청마다 고유 할 것으로 예상했지만 그럴 것 같지는 않습니다.

각 요청에 고유하지 않은 경우 요청을 허용 할 수있는 방법이 있습니까?

업데이트 :
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;
        }
    }
}

예를 들어, 요청을 리디렉션 filterContext.Result = new RedirectResult(...)하면 새 HttpContext가 만들어지기 때문에 항목이 손실됩니다. 자세한 내용은 여기 : stackoverflow.com/questions/16697601/…
Reuel Ribeiro

좋은 답변과 관련된 질문은 stackoverflow.com/q/5219431에 있습니다.
Theophilus

답변:


146

정적 클래스와 정적 인스턴스 필드는 응용 프로그램에 대한 모든 요청간에 공유되며 응용 프로그램 도메인과 수명이 같습니다. 따라서 동기화 문제 등이있을 수 있으므로 정적 인스턴스를 사용할 때는주의해야합니다. 또한 응용 프로그램 풀이 재활용되기 전에 정적 인스턴스가 GC되지 않으므로 정적 인스턴스가 참조하는 모든 항목이 GC되지 않습니다. 메모리 사용 문제가 발생할 수 있습니다.

요청과 수명이 동일한 인스턴스가 필요한 경우 HttpContext.Current.Items컬렉션 을 사용하는 것이 좋습니다 . 이것은 의도적으로 요청을 처리하는 데 필요한 물건을 저장하기위한 장소입니다. 더 나은 디자인과 가독성을 위해 Singleton 패턴을 사용하여 이러한 항목을 관리 할 수 ​​있습니다. 에 인스턴스를 저장하는 Singleton 클래스를 만들면됩니다 HttpContext.Current.Items. (ASP.NET의 공통 라이브러리에는이 목적을위한 일반 SingletonRequest 클래스가 있습니다).


3
관련된 싱글 톤 패턴 샘플을 제공해 주 HttpContext.Current.Items시겠습니까?
Airn5475

내 상황에 대한 자세한 내용 : 웹 응용 프로그램에서 사용자는 공유 클래스 속성을 사용하는 코드 라이브러리를 실행합니다. 이 속성을 사용자별로 지정하고 싶지만이 속성을 다른 기능으로 넘길 필요는 없습니다. 언급 한 디자인을 제대로 처리 할 수 ​​있습니까?
Airn5475

SingletonRequest 클래스를 공유 할 수 있습니까?
Tebo

정적 클래스에 데이터를 저장하지 않습니다. 데이터를 가져 오거나 데이터를 데이터 레이어로 설정하는 경우에만 정적 클래스를 사용합니다. 문제가 있습니까?
번쩍 거리는

"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"-다른 곳에서 읽은 내용과 의미가 상충되지 않기 때문에 이에 대한 출처가 있습니까? AppPool이 재활용되면 관련 App Domain이 완전히 종료되고 GC됩니다. 이러한 상황이 발생하면 루트 (AppDomain)가 없어 관련 정적 인스턴스도 GC됩니다. 풀 재활용의 일부로 새 AppDomain이 만들어지고 연결된 정적 인스턴스가 초기화됩니다.
Nick

30

정적 멤버는 현재 작업자 프로세스의 범위 만 가지므로 다른 작업자가 동일한 작업자 프로세스에 의해 처리되거나 처리되지 않을 수 있으므로 요청과 관련이 없습니다.

  • 특정 사용자와 요청간에 데이터를 공유하려면 HttpContext.Current.Session을 사용하십시오.
  • 특정 요청 내에서 데이터를 공유하려면 HttpContext.Current.Items를 사용하십시오.
  • 전체 응용 프로그램에서 데이터를 공유하려면 해당 메커니즘을 작성하거나 단일 프로세스에서 작동하도록 IIS를 구성하고 단일 응용 프로그램을 작성하십시오.

그건 그렇고, 기본 작업자 프로세스 수는 1이므로 웹에는 정적 멤버가 전체 응용 프로그램의 범위를 가지고 있다고 생각하는 사람들로 가득합니다.


11

유형이 앱 도메인에 포함되어 있기 때문에 앱 도메인이 재활용되지 않거나 요청이 다른 앱 도메인에서 제공되는 경우 정적 클래스가 존재할 것으로 기대합니다.

특정 요청에 특정한 객체를 만드는 몇 가지 방법은 원하는 작업에 따라 다릅니다. 예를 들어 Application.BeginRequest에서 객체를 인스턴스화 한 다음 HttpRequest 객체에 저장하여 모든 객체에서 액세스 할 수 있습니다. 요청 처리 파이프 라인


4

각 요청에 고유하지 않은 경우 요청을 허용 할 수있는 방법이 있습니까?

아니. 정적 멤버는 ASP.NET 프로세스가 소유하고 모든 웹 앱 사용자가 공유 합니다. 세션 변수와 같은 다른 세션 관리 기술로 전환해야합니다.


1

일반적으로 정적 메서드, 속성 및 클래스는 Application 수준 입니다. 응용 프로그램이 존재하는 한 공유됩니다.

ThreadStatic속성 을 사용하여 다른 동작을 지정할 수 있습니다 . 이 경우 현재 스레드에 따라 다르며 각 요청마다 다릅니다.
지나치게 복잡해 보이지만 조언하지는 않습니다.

HttpContext.Current.Items한 요청에 대해 항목 HttpContext.Current.Session을 설정 하거나 한 요청에 대해 한 사용자에 대해 항목 을 설정 하는 데 사용할 수 있습니다 .

그러나 일반적으로와 같은 것을 사용해야하지 않는 한 Server.Transfer가장 좋은 방법은 기본적으로 물건을 한 번 만든 다음 메소드 호출을 통해 명시 적으로 전달하는 것입니다.


3
존 소총은 ThreadStatic이 안전한 결코 우리에게 보여줍니다 ASP.Net을 stackoverflow.com/questions/4791208/...
마크 Lindell

스레드가 요청에 고유하지 않으므로 다운 투표되었습니다. 이 답변을 제거하십시오
seebiscuit
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.