2009-11-05 5 views
12

시스템 : Windows XP SP3, .NET 3.5, 4GB RAM, 이중 1.6gWPF가 메모리에서 큰 BitmapSource를 해제하는 방법은 무엇입니까?

매우 큰 PNG를로드하고 전환하는 (스토리 보드 애니메이션 사용) WPF 응용 프로그램이 있습니다. 이러한 PNG는 8190x1080 해상도입니다. 응용 프로그램이 실행되면 이미지를 캐시하고 시스템 메모리가 천천히 움직입니다. 결국 시스템을 질식시키고 OutOfMemoryException을 throw합니다.

1) 나는로드 할 때 내가 없음으로 BitmapSource는 BitmapCacheOption을 설정하고

2) 응용 프로그램에서 BitmapSource는 개체를 제거하고 : 여기

내가 현재이 해결을 위해 복용하고있는 단계입니다 BitmapSource

3) 일단로드되면 BitmapSource가 고정됩니다.

4) 소스를 사용하는 이미지에 대한 모든 참조와 소스 자체에 대한 참조를 모두 삭제합니다.

5) 위 단계를 수행 한 후 GC.Collect()를 수동으로 호출하면 완료됩니다.

WPF가 이러한 이미지에 대해 메모리에 매달려있는 이유와이를로드하는 데 사용 된 메모리가 제대로 복구되었는지 확인하는 것이 좋습니다.

답변

21

당신은 확실히 이것에 많은 연구를했습니다. 주요 문제는 BitmapCacheOption.None이 기본 BitmapDecoder가 캐시되지 못하게한다는 것입니다.

가 다시)하는 GC.Collect를()를하고있는 300 개 가지의 URI에서 300 개 작은 이미지를로드하고, GC.Collect를을 (전화로이 같은 여러 가지 까다로운 솔루션이 있지만 간단한은 간단하다 :

대신 열린 우리당에서로드의 단지 스트림을 구성하고 BitmapFrame의 생성자에 전달이 작동합니다

var source = new BitmapImage(); 
using(Stream stream = ...) 
{ 
    source.BeginInit(); 
    source.StreamSource = stream; 
    source.CacheOption = BitmapCacheOption.OnLoad; // not a mistake - see below 
    source.EndInit(); 
} 

이유는 완전히 캐시를 비활성화 스트림으로부터 로딩입니다. 최상위 소스가 캐시되지 않을뿐만 아니라 내부 디코더도 캐시되지 않습니다.

왜 BitmapCacheOption.OnLoad입니까? 반 직관적 인 것처럼 보이지만이 플래그는 두 가지 효과가 있습니다. 캐싱이 가능하면 캐싱이 가능하고 EndInit()에서로드가 발생합니다. 우리의 경우 캐싱은 불가능하기 때문에 부하가 즉시 발생합니다.

분명히 UI 스레드에서이 코드를 실행 한 다음 BitmapSource를 고정 시켜서 옮길 수 있습니다.

왜 BitmapCreateOptions.IgnoreImageCache를 사용하지 않았는지 궁금 할 것입니다. 캐시가 URI가 주어지지 않으면 불가능하다는 사실 외에도, IgnoreImageCache는 이미지 캐시를 완전히 무시하지 않습니다. 읽기 전용으로 무시합니다. 따라서 IgnoreImageCache가 설정되어 있어도로드 된 이미지는 여전히 캐시에 삽입됩니다. 차이점은 캐시의 기존 이미지가 무시된다는 것입니다.

+0

BitmapSource source = new BitmapSource()가 컴파일되지 않아 그 이유가 확실하지 않습니다. 오류 'System.Windows.Media.Imaging.BitmapSource'추상 클래스 또는 인터페이스의 인스턴스를 만들 수 없습니다. – discorax

+0

Ahh ... BitmapSource 대신 BitmapImage를 사용할 때 컴파일됩니다. 이제 문제가 어떻게 발생합니까? :) – discorax

+0

이 접근법은 지금까지 유망 해 보입니다. 나는 계속 시험 할 것이다. – discorax

관련 문제