ASP.NET 정적 변수의 수명


78

페이지 클래스 (Global.asax가 아님)에 정의 된 정적 변수에 몇 가지 정보가 있습니다. 다음과 같은 코드에서만 변수를 선언합니다.

protected static int SomeGlobalUnsecureID;
protected static string SomeGlobalUnsecureString;

PageLoad 이벤트에서 변수를 정의합니다. 예를 들어 데이터베이스에서 ID를 확인하고 SomeGlobalUnsecureID와 다른 경우 SomeGlobalUnsecureID 및 String을 다른 곳에서 업데이트하고 그렇지 않으면 그대로 둡니다. 이것은 내 앱에서 완벽하게 안전합니다. 논리 (즉, 이러한 데이터는 안전하지 않고 누구나 액세스 할 수 있으며 문제 없음) 내가 성취하고 싶은 유일한 것은

  1. 연결된 사용자에 관계없이 동일한 양의 메모리를 보유

  2. 영구 정보가 '메모리'의 정보와 다른 경우에만 변경하십시오 (실제로 문자열을 읽는 데 시간이 많이 걸리기 때문입니다.

이제 PageLoad에서 확인 했으므로 다시로드 된 페이지에서 문제가 없습니다. 그러나 내 페이지는 WebMethods로 가득 차 있으며 때로는 정적 변수가 0으로 표시되는 것을 볼 수 있습니다. 그리고 이상한 부분은 다음과 같습니다. 정적 변수가 0이 되어도 세션은 여전히 ​​활성 상태입니다 (따라서 서버 또는 앱 풀 재시작 없음 등).

이것은 나에게 정말 이상합니다. 정적 변수는 응용 프로그램이 종료 될 때까지 값을 유지한다고 가정합니다. 그러나 세션이 만료되지 않았더라도 정적 변수는 0이됩니다. 당신은 무엇을 제안합니까? 응용 프로그램 변수를 사용하는 것이 더 나은 선택입니까? 웹에서 읽은 모든 문서는 응용 프로그램 변수 대신 정적 변수를 제안합니다. 어떻게 든 다르게 선언해야합니까?


1
질문 상단의 선언은 정적 이 아닙니다 .
Andrew Barber

1
'PageLoad 이벤트에서 변수를 정의하십시오.' 초기화를 의미합니까? 변수를 정의하는 것은 당신이 글을 쓸 때하는 일입니다protected static int Something;
Carl G

"이제 PageLoad에서 확인을했기 때문에 다시로드 된 페이지에서 문제가 없습니다." -이것은 일어나기를 기다리는 경쟁 조건처럼 들립니다. 대신 스레드로부터 안전한 지연 초기화를 고려합니다.
millimoose 2013

정적 lass는 다음 재활용까지 지속됩니다. 정적 클래스의 사용이 다른 사람에 변수를 넣어
Mbithy Mbithy

답변:


106

정적 변수는 앱 도메인의 수명 동안 유지됩니다. 따라서 정적 변수를 '재설정'하게 만드는 두 가지 사항은 앱 도메인 다시 시작 또는 새 클래스 사용입니다. aspx 페이지 클래스에 저장된 정적 변수가있는 경우 ASP.NET이 aspx 페이지를 새 클래스로 다시 컴파일하여 이전 페이지 클래스를 새 클래스로 대체하기로 결정하면 정적 변수가 손실 될 수 있습니다.

이러한 이유로 시스템이 클래스를 다시 시작하거나 교체하기로 결정한 경우 ( .NET은 실행중인 앱 도메인에서 클래스 / 어셈블리를 종료하거나 언로드하지 않음 ) 다시 시작 또는 교체를 통해 새 클래스를 가져 오므로 정적 변수가 재설정됩니다. 이것은 App_Code 폴더의 aspx 페이지와 클래스 모두에 적용됩니다.

ASP.NET은 어떤 이유로 든 클래스를 다시 컴파일해야한다고 생각하는 경우 클래스를 대체합니다 ( ASP.NET 동적 컴파일 참조 ).

앱 도메인 다시 시작으로 인한 정적 변수 손실을 방지 할 수는 없지만 클래스 교체에서는이를 방지 할 수 있습니다. aspx 페이지가 아니고 App_Code 디렉터리에없는 클래스에 정적 변수를 넣을 수 있습니다. static class프로그램 의 어딘가에 배치 할 수 있습니다 .

public static class GlobalVariables
{
    public static int SomeGlobalUnsecureID;
    public  static string SomeGlobalUnsecureString;
}

정적 변수는 풀당입니다. 즉, asp.net 사이트를 실행하는 2 개의 풀이있는 경우 2 개의 다른 정적 변수가 있습니다. ( 웹 가든 모드 )

시스템이 이러한 방법 중 하나로 asp.net 응용 프로그램을 다시 시작하면 정적 변수가 손실됩니다.

  1. 풀은 재 컴파일이 필요하다고 결정합니다.
  2. app_offline.htm 파일을 엽니 다.
  3. 풀을 수동으로 다시 시작합니다.
  4. 풀이 정의한 일부 제한에 도달하고 다시 시작합니다.
  5. 어떤 이유로 든 iis 또는 풀을 다시 시작합니다.

이 정적 변수는 스레드로부터 안전하지 않으며 다른 스레드에서 액세스하는 경우 특히 lock 키워드 를 사용해야합니다 .

앱을 다시 시작하면 무슨 일이 있어도 통계가 재설정되므로 실제로 데이터를 유지하려면 사용자 지정 클래스를 사용하여 데이터베이스에 데이터를 저장해야합니다. 당신은에서 사용자 별 정보를 저장할 수 있습니다 세션 상태데이터베이스 세션 상태 모드 . ASP.NET 응용 프로그램 상태 / 변수는 데이터베이스가 아닌 메모리에 저장 되므로 앱 도메인을 다시 시작할 때도 손실되므로 도움이되지 않습니다 .


6
@Aristos 이것은 오래된 질문 일 수 있지만 귀하의 답변은 정확하지 않습니다. 클래스 변수가 정적 인 경우이 클래스의 인스턴스를 만들고 종료하는 것은 중요하지 않습니다. 어셈블리가 메모리에로드 된 상태로 유지되는 한이 변수는 여전히 값을 유지합니다. 그러나 IIS는 호스팅 된 응용 프로그램을 정기적으로 재활용하기 때문에 일부 어셈블리가 언로드 된 다음 다시로드되어 정적 변수 데이터가 손실됩니다. 한 번 봐 가지고
토마스 CG 드 헤나

1
@ ThomasC.G.deVilhena 나는 당신과 같은 말을 (동의합니다)? 잘 입력하지 않았습니까? 제 질문을 수정하고 당신이 말하는이 부분을 고칠 수 있습니까?
Aristos 2012

1
문제는 정적 변수가 aspx 파일 (비 정적 클래스 여야 함)에 정의되어 있다는 것입니다. 응용 프로그램을 다시 시작 (모든 정적 변수를 지움)하는 것 외에도 IIS는 aspx 페이지를 다시 컴파일합니다 (수정되면 또는 다른 이유로) 컴파일 된 새 어셈블리를로드합니다. 새로 컴파일 된 aspx 페이지 / 클래스는 자체 정적 변수가있는 새 클래스입니다. 변수를 정적 클래스로 전환하면 이제 클래스에 대해 aspx 재 컴파일이 발생하지 않기 때문에 응용 프로그램을 다시 시작하는 경우를 제외하고 재설정을 방지 할 수 있습니다.
Carl G

1
@ ThomasC.G.deVilhena이 답변의 일부를 더 정확하게 변경하려면 변경하십시오.
Aristos

1
@CarlG이 답변의 일부를 변경하거나 더 정확하게 만들기 위해 다른 측면을 추가하려는 경우에도 똑같이 제안합니다.
Aristos 2013

21

정적 변수의 수명을 위해 다음 두 가지 사항도 중요하다고 생각합니다.

1-응용 프로그램 풀의 고급 설정에서 "재활용"-> "정기 시간 간격 (분)"설정을 확인합니다. 기본값은 1740입니다. 즉, 애플리케이션 풀 재활용으로 인해 29 시간마다 정적 변수가 손실됩니다. 이 설정은 가능한 메모리 누수를 종료하는 데 사용됩니다. 이 설정은 변경하지 않겠습니다 ..

2-응용 프로그램 풀의 고급 설정에서 "프로세스 모델"-> "유휴 시간 제한 (분)"설정을 확인합니다. 기본값은 20입니다. 즉, 애플리케이션 풀에서 20 분 동안 비활성 상태 일 때마다 작업자 프로세스가 종료 / 일시 중단되어 정적 변수가 손실됩니다. 이 설정은 응용 프로그램 풀이 일정 시간 동안 사용되지 않을 때 리소스를 확보하는 데 사용됩니다. 0으로 설정하여 시간 초과를 비활성화 할 수 있습니다.


1
감사합니다. 제 경우에는 재활용 이 문제였습니다.
이삭

IMHO 기본 재활용 설정은 "이동"할 때 대부분의 응용 프로그램에서 변경되어야합니다. 풀이 언제 재활용되는지에 대해 생각할 필요없이 정확히 알고 싶습니다.
combatc2

-12

정적 변수는 모든 객체를 동일한 값으로 저장하는 데 사용됩니다.

protected void Page_Load(object sender, EventArgs e)
{
    sss s1, s2;
    s1 = new sss();
    s1.TotalMark = 10;
    s2 = new sss();
    s2.TotalMark = 20;
    sss.SchoolName = "St.Joseph's Hr.Sec.S"; //We can access through class and assign common to all
    s1.PrintData();
    s2.PrintData();
}

public class sss
{
    public static string SchoolName { set; get; }
    public int TotalMark { set; get; }
    public string StudentName{set;get;}
    public void PrintData()
    {
        Console.WriteLine(TotalMark);
        Console.WriteLine(SchoolName);
        Console.WriteLine(StudentName);
    }
}

3
아래로 투표했습니다.이 답변은 질문과 관련이 없습니다. (OP는 정적 변수가 어떻게 작동해야하는지 명확하게 이해합니다.-질문은 왜 제대로 작동하지 않는지입니다.)-추가적으로 설명이 잘못되었습니다.
BrainSlugs83
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.