Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

ASP.NET에서 System.Web.HttpApplication 인스턴스는 다중으로 생성됩니다.

일단, 다음의 글이 너무 좋으니 추천 한번 하고. ^^

ASP.NET Application and Page Life Cycle
; http://www.codeproject.com/Articles/73728/ASP-NET-Application-and-Page-Life-Cycle

System.Web.HttpApplication은 요청을 처리하는 하나의 단위입니다. Pool에 보관되기 때문에 재사용이 되어 무한정 생성되지는 않습니다. 이에 대한 테스트는 다음의 코드로 간단하게 할 수 있습니다.

using System;

namespace WebApplication1
{
    public class Global : System.Web.HttpApplication
    {
        public Global()
        {
            System.Diagnostics.Trace.WriteLine("====================== ctor" + this.GetHashCode());
        }
    }
}

실행하고, 간단한 부하 테스트를 해보면 Hash 코드 값이 다른 ctor 로그가 출력됩니다.

그럼, 여기서 궁금한 것이 하나 생깁니다. 그렇다면 Application_Start 이벤트 핸들러가 여러 번 실행될 수도 있다는 것일까요? 실제로 테스트를 해보면,

using System;

namespace WebApplication1
{
    public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            System.Diagnostics.Trace.WriteLine("====================== Application_Start" + this.GetHashCode());
        }
    }
}

로그 출력 결과로는 단 한 번의 이벤트만 발생합니다. 이유는 HttpApplication을 관리하는 HttpApplicationFactory 인스턴스에서 어떤 HttpApplication을 생성하든지 단 한 번만 Application_Start 이벤트가 발생하도록 관리를 하기 때문입니다.

// System.Web.HttpApplicationFactory (System.Web.dll)

internal static void EnsureAppStartCalledForIntegratedMode(HttpContext context, HttpApplication app)
{
    if (!_theApplicationFactory._appOnStartCalled)
    {
        Exception innerException = null;
        HttpApplicationFactory factory = _theApplicationFactory;
        lock (factory)
        {
            if (!_theApplicationFactory._appOnStartCalled)
            {
                using (new DisposableHttpContextWrapper(context))
                {
                    WebBaseEvent.RaiseSystemEvent(_theApplicationFactory, 0x3e9);
                    if (_theApplicationFactory._onStartMethod != null)
                    {
                        app.ProcessSpecialRequest(context, _theApplicationFactory._onStartMethod, _theApplicationFactory._onStartParamCount, _theApplicationFactory, EventArgs.Empty, null);
                    }
                }
            }
            _theApplicationFactory._appOnStartCalled = true;
            innerException = context.Error;
        }
        if (innerException != null)
        {
            throw new HttpException(innerException.Message, innerException);
        }
    }
}

(참고로, HttpApplicationFactory 인스턴스는 System.Web.Hosting.PipelineRuntime에서 관리합니다.)

그런데, 생각해 보니 또 다른 의문이 있습니다. HttpApplication의 속성인 Application 객체는 어떻게 전역 설정을 관리할 수 있는 걸까요? 왜냐하면 Application 속성이 HttpApplication 객체에는 static이 아닌 instance 멤버이기 때문입니다.

// System.Web.HttpApplication (System.Web.dll)

public class HttpApplication : IComponent, IDisposable, IHttpAsyncHandler, IHttpHandler, IRequestCompletedNotifier, ISyncContext
{
    private HttpApplicationState _state;
    // ...[생략]...
}

가령 웹 사이트 단위로 고유한 값을 저장하고 싶을 때 다음과 같이 프로그램을 하게 되는데요.

using System;

namespace WebApplication1
{
    public class Global : System.Web.HttpApplication
    {
        protected void Application_Start(object sender, EventArgs e)
        {
            this.Application["test"] = 0;
        }
    }
}

실제로 테스트를 해보면, 다중으로 생성되는 System.Web.HttpApplication 인스턴스에 상관없이 HttpApplicationState 상태 관리는 단일하게 적용이 됩니다.

그 이유는, 역시 HttpApplicationFactory에서 HttpApplicationState 객체를 하나만 생성하고 HttpApplication에 넘겨 주는 식으로 관리를 하기 때문에 가능한 것입니다.

// System.Web.HttpApplication (System.Web.dll)

internal void InitSpecial(HttpApplicationState state, MethodInfo[] handlers, IntPtr appContext, HttpContext context)
{
    this._state = state;

    // ...[생략]...   
}

위와 같이 HttpApplicationFactory 측에서 HttpApplication.InitSpecial을 호출해야만 HttpApplicationState 인스턴스가 유효하게 됩니다. 따라서 이 메서드가 불리기 이전까지는 HttpApplication 인스턴스 내에서 this.Application 객체를 사용할 수가 없습니다.

이 때문에 Global 타입의 생성자에서 this.Application 저장소를 접근하면,

using System;

namespace WebApplication1
{
    public class Global : System.Web.HttpApplication
    {
        public Global()
        {
            this.Application["test"] = 0;
        }
    }
}

NullReferenceException 예외가 발생하는 것입니다.

Object reference not set to an instance of an object. 
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error: 


Line 11: 
Line 12:             this.Application["test"] = 0;
Line 13:         }
Line 14: 




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 11/17/2016]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 151  152  153  154  155  156  157  158  159  160  161  162  [163]  164  165  ...
NoWriterDateCnt.TitleFile(s)
1006정성태3/15/201126903.NET Framework: 206. XML/XSD - 외래키처럼 참조 제한 거는 방법파일 다운로드1
1005정성태3/11/201136766개발 환경 구성: 110. 엑셀 매크로 함수 관련 오류 [2]
1004정성태3/3/201126009개발 환경 구성: 109. SharePoint Health Analyzer 디스크 부족 경고 제어
1003정성태3/3/201126966오류 유형: 113. SQL Server - DB Attach 시 Parameter name: nColIndex 오류 발생
1002정성태3/2/201125296Team Foundation Server: 44. TFS 설치 후, Team Portal의 Dashboard를 빠르게 확인하는 방법
1001정성태3/2/201129399Team Foundation Server: 43. TFS 2010 + SharePoint 2010 설치
1000정성태3/1/201134457오류 유형: 112. Remote FX RDP 연결 시 오류 유형 2가지 [5]
999정성태2/28/201147632개발 환경 구성: 108. RemoteFX - Windows 7 가상 머신에서 DirectX 9c 환경을 제공 [5]
998정성태2/27/201121549Team Foundation Server: 42. TFS Application-Tier만 재설치
996정성태2/12/201139047디버깅 기술: 35. windbg - 분석 예: 시작하자마자 비정상 종료하는 프로세스 - NullReferenceException
995정성태2/11/201157598.NET Framework: 205. 코드(C#)를 통한 풀 덤프 만드는 방법 [4]
994정성태2/10/201137403디버깅 기술: 34. Windbg - ERROR: Unable to load DLL mscordacwks_x86_x86_2.0.50727.4200.dll, Win32 error 0n2 [1]
993정성태2/10/201129816개발 환경 구성: 107. 하나의 WPF 프로젝트를 WinExe / Library로 빌드하는 방법
992정성태10/15/201130674개발 환경 구성: 106. VSS(Volume Shadow Service)를 이용한 Hyper-V VM 백업/복원 [2]
991정성태2/6/201150070개발 환경 구성: 105. 풀 덤프 파일을 남기는 방법 [4]
990정성태2/2/201135206개발 환경 구성: 104. Visual C++ Custom Build Tool 사용예 [1]파일 다운로드1
989정성태2/1/201131663개발 환경 구성: 103. DOS batch - 동기 방식으로 원격 서비스 제어
988정성태1/30/201127682개발 환경 구성: 102. MSBuild - DefineConstants에 다중 전처리 값 설정
987정성태1/29/201140975디버깅 기술: 33. PDB Symbol 로드 오류 - Cannot find or open the PDB file. [2]
986정성태1/26/201132397.NET Framework: 204. 분리된 ThreadPool 사용 - Smart Thread Pool
985정성태1/25/201129031디버깅 기술: 32. 인증서로 서명된 닷넷 어셈블리의 실행 지연 현상
984정성태1/25/201123612개발 환경 구성: 101. SharePoint 2010 - Form Design
983정성태1/23/201128928제니퍼 .NET: 15. 눈으로 확인하는 maxWorkerThreads, minFreeThreads 설정값 [1]
982정성태1/22/201125850개발 환경 구성: 100. SharePoint 2010 - iPad 친화적인 게시판 만들기 (사용자 지정 목록) [1]
981정성태1/19/201122040개발 환경 구성: 99. SharePoint 2010 - 웹 애플리케이션 생성 시 고려해야 할 점. [1]
980정성태1/19/201133525개발 환경 구성: 98. SharePoint 2010 - Office Web Apps 설치
... 151  152  153  154  155  156  157  158  159  160  161  162  [163]  164  165  ...