2012-10-11 3 views
7

객체를 재활용하는 방법을 생각하면서이 아이디어를 얻었습니다. 나는 메모리 풀링이 어떻게 작동 하는지를보기위한 실험으로 이것을하고 있으며 99 %의 시나리오에서 이것은 매우 불필요하다는 것을 깨닫는다.GC 파괴 시도에 객체 유지

그러나 질문이 있습니다. GC가 객체를 유지하도록하는 방법이 있습니까? 다시 말해, GC에게 객체를 파괴하지 말라고 지시하고 객체 대신 객체를 사용할 수있는 새로운 참조를 목록에 작성한다고 말할 수 있습니까?

~myObject() 
{ 
    ((List<myObject>)HttpContext.Current.Items[typeof(T).ToString()]).add(this);//Lets assume this is ASP 
} 

이 목록에이 개체에 대한 포인터를 추가하지만, 오브젝트가 파괴되면 내가 얻을 것이다 :이 테스트하지 않았습니다하지만 문제는, 나는 목록에이 같은 것을 추가하는 경우이다 객체가 더 이상 존재하지 않기 때문에 null 포인터 예외. 그러나 GC가이 항목을 수집하지 않고 개체를 보관하지 않도록 할 수 있습니까?

저는 이것이 대부분의 프로그래머가 "왜 이럴 수 있겠습니까?"라고하는 물건 유형이라는 것을 알고 있습니다. 그러나 반면에 프로그래밍은 새로운 것을 시도하고 새로운 것을 배우는 것에 관한 것입니다. 어떤 제안, 생각, 구현? 어떤 도움이라도 대단히 감사하겠습니다!

답변

6

예, 이것은 합법입니다. 이것을 '부활'이라고합니다. 참조를 'live'어딘가에 할당하면 해당 객체는 더 이상 가비지로 간주되지 않습니다.

GC.ReRegisterForFinalize(this)을 사용하여 파이널 라이즈를 다시 등록해야합니다. 또는 다음에 오브젝트가 가비지가되면 파이널 라이즈되지 않습니다 (소멸자가 호출되지 않음).

개체 부활에 대한 자세한 내용은 this MSDN Magazine article에서 읽을 수 있습니다.

0

GC는 명시 적으로 해제되는 범위를 벗어나서 참조가 사라진 객체 만 처리합니다.

어느 방법이든 GC가 개체를 수집하는 것을 방지하려면 KeepAliveSuppressFinalize 메서드를 사용하는 것이 좋습니다. 일단 당신이 그 (것)들을 가진 진실하게 끝내면 당신은 ReRegisterForFinalize를 사용하여 수집가에 의해 줍기 위하여 그 (것)들을 등록 할 필요가있을 것이다.

+0

SuppressFinalize는 컬렉션이 아니라 소멸자 만 실행하는 것을 취소합니다. KeepAlive는 더 좋지만 어딘가에 불러야합니다. 실용적이지는 않습니다. –

2

예, 가능하며 이름이 : 부활입니다.

하지만 개체가 파괴되면 개체가 더 이상 존재하지 않기 때문에 널 포인터 예외가 발생합니다.

훨씬 더 나쁜 포인터 (참조) 오류가 발생합니다. 그리고 아마도 블루 스크린이나 서버가 망가질 수도 있습니다. 그러나 운 좋게도 CLR은 그렇게하지 않을 것입니다. 운명을 정한 인스턴스를 어떤 종류의 목록에 넣기 만하면 다시 도달 할 수 있고 다시 회수되지 않습니다.

개체를 여러 번 재활용하려는 경우 GC.ReRegisterForFinalize(x)을 호출해야합니다.

실용적인 답변 :하지 마세요. 소멸자만으로도 상당한 오버 헤드가 발생하며이를 해결하는 데는 여러 가지 방법이 있습니다.