2009-10-29 3 views
1

간단한 설명을 고정하지 않는 것 캐시 항목 콜백 및 기타 방법에 사용 한시간 안에 만료 될 캐시 항목. 또한 캐시 항목이 만료 될 때 호출되는 콜백 메서드가 있습니다.이 메서드는 Render에서 만든 파일을 삭제합니다. Page_Init 메서드에서 Render 메서드가 디스크에 쓴 파일에 액세스하려고합니다. 이 두 메소드에는 모두 lock 문이있어 개인 정적 객체를 잠급니다.잠금 내가 생성 할 수

가 의도 : 파일을 봉사하고있는 동안

가 (또는 날짜, 내용이 많다는 점 만점) 너무 오래된지기 전에 삭제됩니다 기본적으로 디스크에 자신의 복사본을 기록하는 페이지를 만들려면, 존재하는 경우 디스크에.

관찰 된 문제 :

이것은 실제로 두 가지 문제입니다. 페이지 요청은 예상 한대로 수행되며 페이지를 디스크로 렌더링하여 즉시 제공하고 만료 항목을 캐시에 추가합니다. 테스트를 위해 만료 시간은 1 분입니다.

그런 다음 콜백 메서드가 60 초 후에 호출되고 파일을 삭제할 것으로 예상합니다. 그렇지 않습니다.

(인수의 이유로) 브라우저에서 페이지를 새로 고칩니다. 그런 다음 콜백 메소드가 호출되고 잠금 객체에 잠금을 설정하는 것을 볼 수 있습니다. Page_Init도 호출되고 동일한 객체에 잠금을 설정합니다. 그러나 두 방법 모두 잠금 코드 블록을 입력하고 실행을 계속합니다.

결과는 다음과 같습니다. 렌더 검사 파일이 있고, 콜백 메소드가 파일을 삭제하고, 렌더 메소드가 지금 삭제 된 파일을 제공하려고합니다.

끔찍 간단한 코드 추출 :

이 가
public class MyPage : Page 
{ 
    private static Object lockObject = new Obect(); 

    protected void Page_Init(...) 
    { 
    if (File.Exists(...)) 
    { 
     lock (lockObject) 
     { 
     if (File.Exists(...)) 
     { 
      Server.Transfer(...); 
     } 
     } 
    } 
    } 

    protected override void Render(...) 
    { 
    If (!File.Exists(...)) 
    { 
     // write file out and serve initial copy from memory 
     Cache.Add(..., new CacheItemRemovedCallback(DoCacheItemRemovedCallback)); 
    } 
    } 

    private static void DoCacheItemRemovedCallback(...) 
    { 
    lock (lockObject) 
    { 
     If (File.Exists(...)) 
     File.Delete(...); 
    } 
    } 
} 

사람이이 제발 설명 할 수 있습니까? 나는 콜백 메서드가 본질적으로 게으르다는 것을 이해하고 요청을 한 번만 호출하기 때문에 .NET1.1의 스레딩은 두 개의 lock() 블록을 동시에 입력 할 수 없다는 것을 충분히 이해할 수 있습니까?

감사합니다.

매트.

+0

관련 없음,하지만 :'private static Object lockObject = new Obect()'- 웹 페이지에 있습니까? 이는 * 모든 * 요청이 잠금을 공유한다는 것을 의미합니다 - 의도 한 것입니까? –

+0

아마 내가 제대로 이해하지 못 하겠지만 OutputCache 지시문의 기능을 복제하고있는 것처럼 보입니다. http://msdn.microsoft.com/en-us/library/hdxfb6cy(VS.71).aspx – PhilPursglove

+0

[뻔뻔스러운 침묵] 예, 그렇습니다. 사실, .NET1.1에 제공되지 않았다는 인상을 받았습니다. 나는 이제 내 머리를 찢어 버리고 그 이유와 1.1 OutputCache에 결함이 있는지 기억하려고 노력할 것입니다. 그런 다음 그것을 사용할 것입니다. 감사합니다. [더 많은 침묵] –

답변

1

솔루션이 작동하지 않는 이유는 확실하지,하지만 그

내가 완전히 다른 경로를 제안 ... 결과를 고려, 좋은 일이 될 수 있습니다. 파일을 관리하는 프로세스와 파일을 요청하는 프로세스를 분리하십시오.

요청은 캐시로 이동하여 파일의 전체 경로를 가져 와서 클라이언트로 보내야합니다.

요청에 바인딩되지 않은 다른 프로세스가 파일을 만들고 업데이트해야합니다. 첫 번째 사용/액세스시 파일을 만들고 캐시에 전체 경로를 저장합니다 (만료되지 않도록 설정). 규칙적인/적절한 간격으로이라는 다른 임의의 이름을 가진 파일 을 다시 만들고 캐시에이 새 경로를 설정 한 다음 이전 요청 파일을 삭제합니다 (다른 요청에 의해 잠기지 않도록주의).

스레드 또는 ThreadPool을 사용하여 응용 프로그램 시작시이 파일 관리 프로세스를 시작할 수 있습니다. 파일 관리와 요청을 연결하면 프로세스가 동시에 실행되므로 항상 피하는 것이 가장 좋은 스레드 동기화를 수행해야하므로 문제가 발생할 수 있습니다.

+0

내가 마지막으로 수행 한 작업은 캐시 만료시 파일을 삭제하지 않고 LastWrite 및 LastModified 스탬프 만 확인하여 방정식에서 캐시를 완전히 제거하는 것입니다. 이를 위해서는 익스플로러에서 타임 스탬프의 변경 사항을 관찰하지 않았거나 이전에 덮어 쓴 파일을 프로그래밍 방식으로 체크 인하므로 파일을 새 버전으로 덮어 쓸 때 파일을 다시 스탬프해야합니다. –

0

먼저해야 할 일은 스레드 창을 열고 Page_Init이 실행중인 스레드와 콜백이 실행중인 스레드를 관찰하는 것입니다. 두 메서드가 같은 개체에 잠금을 설정할 수 있다는 것을 알고있는 유일한 방법은 같은 스레드에서 실행중인 경우입니다. Server.Transfer를 실제로 어떻게 작동하는지

편집

여기 진짜 문제입니다. Server.Transfer는 요청이 서버의 다른 URL로 전송 될 예정임을 나타내는 ASP.NET 내부 정보를 구성합니다. 그런 다음 Response.End를 호출하여 ThreadAbortException을 던집니다. 그 당시에는 실제 데이터가 읽히거나 클라이언트에 전송되지 않았습니다.

이제 예외가 발생하면 코드 실행으로 인해 코드 블록이 잠금으로 보호됩니다. 이 때 Call Back 기능은 파일을 잠그고 삭제할 수 있습니다.

이제 어딘가 깊은 ASP 내부.NET에서 ThreadAbortException이 어떤 식 으로든 처리되고 새 URL에 대한 요청이 처리됩니다. 현재 파일이 누락 된 것으로 나타납니다.

+0

조언을 주셔서 감사합니다. 실제로 스레드 창이 있다는 것을 깨닫지 못했습니다! 어쨌든, 당신이 옳다는 것을 알았고 하나의 정적 객체에 대한 잠금을 갖는 동안 자신의 lock 문 블록을 각각 입력 할 수있는 두 개의 스레드가 있다는 것을 알았습니다. 그러나이 사실을 이해하면 Microsoft가해야한다고 말한 것에 반대합니다. 내가 '스레드'라는 용어를 다른 용도로 사용하는 것과 혼동하지 않는 한 : http://msdn.microsoft.com/en-us/library/c5kehkcz(VS.71).aspx –

+0

혼란스럽지 않습니다. 두 개의 다른 스레드가 동시에 같은 객체를 잠글 수 없습니다. 기간. 다른 일이 일어나고 있습니다. lockObject에'readonly'를 추가해, 치환 할 수 없게합니다. 어떻게이 행동을 정확히 관찰 할 수 있습니까? – AnthonyWJones

+0

코드를 자세히 살펴 보겠습니다. 외부 관찰은 Server.Transfer를 시도 할 때 디스크에 시각적으로 캐시 된 페이지가 예외임을 나타냅니다. 거기에 있어야합니다. 전송하기 바로 전에 존재 여부를 확인하기 때문입니다. 그러나 전송이 진행되면 예외가 발생합니다. 문제의 안쪽보기는 두 lock 문이 동시에 실행되는 것을 보여줍니다. 하나는 캐시에서 객체를 요청할 때 다른 객체보다 앞서옵니다. 나는 이것이 느린 프레임 워크 호출을하지 않기 때문에 다른 스레드가 앞서 갈 수 있다고 가정 할 것이다. –

관련 문제