2009-08-26 9 views
6

나는 WriteableBitmap 메모리를 해제하는 방법을 알아 내려고하고있다.WPF WriteableBitmap 메모리 누수?

다음 코드 절에서 WriteableBitmap의 백 버퍼를 "BigImage"(3600 * 4800 px, 테스트 용)의 많은 양의 데이터로 채 웁니다. 비트 맵과 이미지가 일치하는 행을 주석 처리하면 null로 설정하면 메모리가 해제되지 않고 응용 프로그램이 ~ 230MB를 소모하며 이미지와 비트 맵이 더 이상 사용되지 않을 때도 !

코드 끝에서 알 수 있듯이 GC.Collect()를 호출하여 메모리를 해제해야합니다.

그렇다면 WriteableBitmap 객체에서 사용하는 메모리를 해제하는 올바른 방법은 무엇입니까? GC.Collect()가 유일한 방법입니까?

도움이 될 것입니다.

추신. 내 하찮은 영어 실력에 죄송하다는 말씀을 드리고 싶습니다.

private void buttonTest_Click(object sender, RoutedEventArgs e) 
{ 
      Image image = new Image(); 
      image.Source = new BitmapImage(new Uri("BigImage")); 

      WriteableBitmap bitmap = new WriteableBitmap(
       (BitmapSource)image.Source); 

      bitmap.Lock(); 

      // Bitmap processing 

      bitmap.Unlock(); 

      image = null; 
      bitmap = null; 

      GC.Collect(); 
} 
+0

http://stackoverflow.com/questions/1534983/how-to-dispose-a-writeable-bitmap-wpf/2422496#2422496 – nyxtom

답변

0

그들은 여전히 ​​로컬로 참조되고, 따라서 루트 참조로 간주되기 때문에이를 정리하지 않습니다 nullimagebitmap을 설정하지 않고 GC를 강제로. 이것은 WriteableBitmap과 특별히 관련이 없으며 GC가 어떻게 작동하는지 질문합니다.

null으로 설정하지 않은 경우 가비지 수집을 강제 실행하지 않으면 메소드가 존재하고 GC가 발생하면 수집됩니다. 위의 권장 사항은 컬렉션 자체를 강요하는 것입니다. 성능 향상에 도움이되는 것보다는 성능에 해를 끼칠 수 있기 때문입니다.

+0

이 도와 주셔서 모두 감사를 참조하십시오. 가비지 수집기가 이미지 및 비트 맵에서 사용하는 메모리를 수집하지 않는 것 같습니다. 내가 null에 할당 된 행을 주석 처리하고 메소드가 실행을 마친 후에는 전체 애플리케이션에서 사용되는 메모리가 ~ 234MB 정도 남아 있습니다. 정말 귀찮은 동작처럼 보입니다. 다시 한 번 감사드립니다. – Mario

+0

얼마나 남았습니까? 가비지 컬렉터가 실제로 수집하려고하는지 확신합니까? perfmon을 열고 GC 카운터를보고 실제로 수집하려고하는지 확인하십시오. 그렇지 않다면 걱정할 필요가 없습니다. 메모리가 부족하여 GC가 필요하지 않습니다. –

+0

도움과 인내심에 감사드립니다. 나는 GC 성능 카운터를 볼 수, 그리고 난 다음 데이터 파악 솜 도움이 필요하지만, GC에 소요되는 시간의 낮은 %가 한 모든 힙에 #Bytes은 1,115,176,000 #GC는 845,000 #induce의 GC 5.0 처리를 그것이 필요는 없습니다) GC.Collect를 (호출을 보이지만, 그들은 ommited 때 응용 프로그램이 닫힐 때까지 사용 된 메모리는 234메가바이트 ~에 남아 있기 때문에 두 개체 (이미지와 비트 맵)의 널 대입이있다. – Mario

1

일반적으로 메모리는 결국 필요에 따라 자동으로 해제되어야합니다.

그러나 이러한 일이 발생하려면 개체가 실제로 사용되지 않았는지 확인해야합니다. "더 이상 사용되지 않는"참조를 포함하여 개체에 대한 참조가 어디에도 존재할 수 없습니다. 따라서 특히 WriteableBitmap과 원본 BitmapSource를 수명이 긴 클래스의 변수에 배치하면 컨테이너가 출시 될 때까지 해제되지 않습니다.

또한 WPF는 유지 된 GFX 모델을 사용합니다. 렌더링 할 때 실제로 렌더링하는 방법은 입니다.을 렌더링하는 것입니다. 비트 맵을 렌더링하는 방법에 대한 "지침"에는 비트 맵에 대한 참조가 포함되어 있습니다. 따라서 큰 비트 맵을 렌더링 한 다음 잠시 동안 (최소한 화면에있는만큼 - 화면의 버전이 작더라도) 이미지는 유지됩니다.

실제로; 이러한 비트 맵에 대한 참조는 필요할 때만 저장하고, 사용하는 컨텍스트가 오래 지속되는 경우 (긴 메서드 호출 또는 비트 맵에 대한 참조를 사용하여 클로저를 생성하는 메서드 호출 또는 장시간 호출의 멤버가 아닌 경우) 그런 다음 더 이상 필요하지 않으면 null로 설정하십시오.

수동으로 메모리를 비울 필요는 없습니다. GC.Collect()는 불필요합니다. 일반적으로 벤치마킹 중 GC.Collect를 사용하여 메모리 사용량을 확인하고 깨끗한 슬레이트로 시작할 수 있습니다. 일반적으로 GC.Collect()를 호출하면 전반적인 성능이 저하됩니다.