2010-11-25 2 views
2

클래스에 "Dispose"가 모든 이벤트를 unhooks하고 해당 객체를 참조하는 타이머를 삭제한다는 것을 확인하기위한 단위 테스트를 작성했습니다.WeakReference.IsLive()가 false가되기 전에 전체 가비지 수집 후에 지연이 있습니까?

그러나 가끔 WeakReference.IsLive()는 false를 반환 할 때 true를 반환합니까?

그래서 WeakReference.IsLive()가 업데이트되기 전에 전체 GC 후에 지연이 있습니까?

그렇지 않다면, 반복 할 수없는 결과를 줄 수있는 다른 것을 생각해 낼 수 있습니까?

WeakReference weekJobWatchDog = new WeakReference(jobWatchDog); 
jobWatchDog = null; 

// not collected before Dispose called due to timer and events etc 
GC.Collect(); GC.Collect(); 
Assert.IsTrue(weekJobWatchDog.IsAlive); 

((IDisposable)weekJobWatchDog.Target).Dispose(); 

// is now collected as Dispose unlocked all events and dispoed the timer 
GC.Collect(); GC.Collect(); 
Assert.IsFalse(weekJobWatchDog.IsAlive); // sometimes this fails, about 1 in 4 runs 

참조 관련 그러나 다른 질문도 Testing Finalizers and IDisposable.

How can I write a unit test to determine whether an object can be garbage collected?에는 GC.WaitForPendingFinalizers()를 호출하는 솔루션이 있지만 GC.WaitForPendingFinalizers()를 호출하지 않아야합니다. 따라서 처리 작업을 증명하고 싶은데, 파이널 라이저를 실행할 필요가 없습니다. .

+0

WaitForPendingFinalizers를 호출 해 보셨습니까? – Henrik

+0

@Henrik, 아니요, 우리가 기다리고 자하는 파이널 라이저를 가지고 있지 않기 때문에 –

답변

0

이 문제가되었다 그 I했다 :

당신이 System.Timers에 폐기()를 호출합니다. 타이머 Win32 타이머가 파괴되기 전에 반환 할 수 있습니다. 따라서 타이머를 유지하는 관리되지 않는 공간에는 여전히 "루트"가 있습니다. 시간에는 내 개체를 살아있는 이벤트 처리기가있었습니다.

이것은 매우시기 적절하게 관련되어 있으므로 대부분 타이머가 GCed가되어 내 개체가됩니다. 그러나 가끔씩 (10 회에 1 번) Timer가 살아있게 유지 될 것이고 내 객체도 유지 될 것입니다.

짧은 수면()은 내 테스트를 100 % 통과 시키므로 타이머를 제거하기 전에 타이머의 이벤트를 언 후킹하므로 타이머가 내 객체를 유지할 수 없습니다. WeakReference를의의 isLive 속성이 참조가 의미 영원히 폐허가되고, 그 값을 체크 할 필요는 없습니다, false를 돌려주는 경우

How do I safely dispose a System.Timers.Timer?

0

Collect 메서드는 차단하지 않기 때문에 GC가 IsAlive을 테스트하는 시점에 개체를 수집하지 못했다고 추측합니다.

(그리고 you can only trust IsAlive when it returns false 것을 잊지 마세요.)

나는 당신이 기다릴 자신의 파이 나라가없는 경우에도 솔루션, WaitForPendingFinalizers 같은 뭔가를 차단 호출해야 할 수도 있습니다 가정합니다. (. 내가 대신 사용할 수있는 다른 적절한 차단 방법이 있는지 확실하지 않습니다)

+0

저는 항상 Collect 메소드가 기본적으로 차단되었다고 생각합니다. 소스가 차단되지 않았습니까? –

+1

@Ian : 나는 네가 옳을 수도 있다고 생각한다. 어느 쪽인가를 확인하는 확실한 서류를 찾을 수 없습니다. GC 자체는 전체 수집 기간 동안 모든 응용 프로그램 스레드를 반드시 일시 중단하지는 않습니다 (워크 스테이션 GC의 비 동시 버전을 실행하는 경우는 제외). 그러나 여기에서 몇 가지 테스트를 수행하여 '수집 '메소드 *가 차단되고있다. 어쩌면 전문가가 몇 가지 구체적인 답을 얻어 낼 수 있습니다. – LukeH

-2

참조하십시오. true를 돌려 준다면 참조가 일 수도 있고 일 수도 있지만 강한 참조로 값을 캡처하려고 시도 할 때까지는 알 수 없습니다. WeakReference가 특정한 정도의 적시성으로 무효화되거나 실제로 관심이없는 한 그 가치를 받아 들여서는 안됩니다. WeakReferences 목록을 정리하고 죽은 것을 제거하는 등의 작업을 수행하는 경우 IsAlive 속성을 사용하면 가비지 수집 대상이 될 수있는 항목에 대한 강력한 참조를 만들지 않고도 정상적으로 삭제 된 항목을 식별 할 수 있습니다.목록에있는 약한 참조가 정리 대상이 될 수있는시기에 대한 특별한 보장은 없지만 (1) 메모리 압박이있을 때 그러한 자격이 더 적시 될 것입니다. (2) 기억력이 없을 때, 적시성은 일반적으로 문제가되지 않는다.