2010-06-15 2 views
1

이미지를 데이터베이스로 캡처하고 저장하는 응용 프로그램을 개발했지만 메모리 사용에 문제가 있습니다. 내 도메인 객체에 나는 3 개 속성이 있습니다WPF에서 바이트 배열의 이미지 표시 - 메모리 문제

이미지 - 바이트 배열, 내용

이 RealImageThumb jpg이 있습니다 - 바이트 배열이 BitmapImage로 변환 축소, 다른 썸네일

을 가진있는 gridview에서 사용자에게 표시

RealImage - 바이트 배열이 비트 맵 소스로 변환 된 setter가 없으며 사용자가이 필드를 가리키면 툴팁에 표시됩니다.

내가 가진 문제는 사용자가 차례로 각 이미지를 가리키면 메모리 사용이 나선 소리가 난다는 것입니다. 사용자가 비트 맵 소스를 생성하고 메모리가 해제되지 않은 상태에서 RealImage에 배킹 속성을 부여하고 null에 할당하려고했지만 메모리가 해제되지 않은 것을 알았습니다 (쓰레기를 기다리는 중). 수집기?).

편집 :

이게 무슨 의미입니까? 아래에 툴팁에 아무 것도 표시되지 않지만, WeakReference<BitmapImage>을 정의하고 정의하면 System.WeakReference에 형식 매개 변수 오류가 발생합니다.

private WeakReference _realImage; 
     public virtual BitmapImage RealImage 
     { 
      get 
      { 
       if (_realImage == null || _realImage.Target == null) 
       { 

        if (Image == null) return null; 
        var newBitmapImage = new BitmapImage(); 
        newBitmapImage.BeginInit(); 
        newBitmapImage.CacheOption = BitmapCacheOption.None; 
        newBitmapImage.CreateOptions = BitmapCreateOptions.IgnoreImageCache; 
        newBitmapImage.StreamSource = new MemoryStream(Image); 
        newBitmapImage.EndInit(); 
        _realImage = new WeakReference(newBitmapImage); 
       } 

       return (BitmapImage)_realImage.Target; 
      } 
     } 

답변

3

당신은 세 가지를 수행해야합니다

  1. 데이터를 제공하기 위해 BitmapImage 사용 StreamSource를 구성. UriSource를 사용하지 않거나 Uri를 생성자에 전달하면 이미지가 이미지 캐시에 추가됩니다.

  2. 도메인 객체의 RealImage 구현에서 WeakReference를 BitmapImage 자체가 아닌 BitmapImage에 저장하십시오. RealImage를 가져 오면 WeakReference 또는 WeakReference.Target이 null이면 새 BitmapImage와 이에 대한 새로운 WeakReference를 만듭니다.

  3. 이 볼 경우에만 시각적 트리에 이미지 컨트롤을 포함하는 템플릿 전환과 함께 사용하십시오 DataTrigger 여기

DataTrigger을 가진 것을 포함하여 3 단계에 필요한 템플릿은 다음과 같습니다

이제
<DataTemplate x:Key="EmptyTemplate"> 
</DataTemplate> 

<DataTemplate x:Key="RealImageTemplate"> 
    <Image Source="{Binding RealImage.Target}" Width="300" Height="300" /> 
</DataTemplate> 

<DataTemplate x:Key="RealImageWhenVisible"> 

    <!-- Use EmptyTemplate when I am not visible --> 
    <ContentPresenter x:Name="Presenter" 
        Content="{Binding}" 
        ContentTemplate="{StaticResource EmptyTemplate}"/> 

    <!-- Switch to RealImageTemplate when I am visible --> 
    <DataTemplate.Triggers> 
    <DataTrigger Binding="{Binding IsVisible, RelativeSource={RelativeSource Self}}" 
       Value="True"> 
     <Setter TargetName="Presenter" 
       Property="ContentPresenter.ContentTemplate" 
       Value="{StaticResource RealImageTemplate}" /> 
    </DataTrigger> 
    </DataTemplate.Triggers> 
</DataTemplate> 

이 같이 당신의 도구 설명을 정의 할 수 있습니다

<Rectangle Width="40" Height="40" Fill="Blue"> 
    <Rectangle.ToolTip> 
    <ContentPresenter Content="{Binding}" 
         ContentTemplate="{StaticResource RealImageWhenVisible}" /> 
    </Rectangle.ToolTip> 
</Rectangle> 

작동 원리 :

  • 외부 ContentPresenter에가 보이지 않는

    는, 내부 ContentPresenter에이 EmptyTemplate이있을 것이다 그래서 이미지가로드되지 않습니다 : 서로 내부에 두 개의 ContentPresenters이 있습니다.
  • 외부 ContentPresenter가 표시되면 내부 ContentPresenter에 RealImageTemplate이 있으므로 이미지가로드되고 표시됩니다.

이렇게해야하는 이유는 도구 설명이 표시되면 팝업을 삭제하지 않음으로써 성능을 최적화하려고 할 수 있기 때문입니다.

업데이트

당신이 일을 해야지 RealImage에 대한 게시, 거의 정확히 내가 생각하고 있었는데 무엇 코드입니다. 오늘 아침에 SourceUri가 지정되지 않은 한 BitmapCacheOption 또는 BitmapCreateOption을 설정할 필요가 없다는 것을 깨달았습니다. 나는 이것을 반영하고 WeakReference를 명확히하기 위해 나의 대답을 업데이트했다. 또한 템플릿의 버그를 수정했습니다. "RealImage.Target"에 바인딩해야 할 때 "RealImage"에 바인딩했습니다.

+0

문제가 발생했습니다. 자세한 내용은 내 질문을 업데이트했습니다. 감사합니다 – ChrisFletcher

+0

질문에 추가 한 코드가 올바르게 보입니다. 몇 가지 사항을 명확히하고 RealImage 바인딩을 RealImage.Target으로 변경하기 위해 답변을 업데이트했습니다. 이 방법이 효과가 있습니까? 그렇지 않다면 사용하려고 할 때 어떤 일이 발생합니까? –