2012-11-13 33 views
8

Tôi đã làm việc trên một ứng dụng WP7, đó là ứng dụng thư viện hình ảnh, với các thao tác thu phóng cơ bản và thao tác vuốt được triển khai.Không thể tìm thấy rò rỉ bộ nhớ

Vì mục đích thử nghiệm, tôi đã biên dịch ứng dụng bằng hình ảnh ngoại tuyến (tên tệp của chúng được đánh số) được đặt thành Nội dung và truy cập chúng qua chuỗi được mã hóa cứng (sẽ được thay thế sau).

Nhưng nhận ra rằng ứng dụng tiêu thụ rất nhiều bộ nhớ. Tôi nghĩ đó là do hình ảnh và tìm thấy this blog; hình ảnh luôn được lưu vào bộ nhớ cache. Tôi đã sử dụng mã từ blog để khắc phục điều này. Vẫn còn bộ nhớ không được phát hành, mặc dù tỷ lệ tiêu thụ đã giảm xuống.

Để cố gắng cuối cùng, tôi đã tạo một ứng dụng thử nghiệm khác với nút tính năng cơ bản 2 để điều hướng và điều khiển hình ảnh cho hình ảnh, chỉ để đảm bảo đó không phải là mã cử chỉ của tôi.

Đây là XAML

<Grid x:Name="LayoutRoot" Background="Transparent"> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Image Grid.Row="0" x:Name="ImageHolder" Height="Auto" Width="Auto" Stretch="Uniform" Tap="image_Tap" /> 
    <TextBlock x:Name="MemUsage" /> 
    <StackPanel Grid.Row="1" Orientation="Horizontal"> 
     <Button x:Name="PrevButton" Content="Prev" Width="240" Click="btnPrev_Click"/> 
     <Button x:Name="NextButton" Content="Next" Width="240" Click="btnNext_Click"/> 
    </StackPanel> 
</Grid> 

Đây là cs nộp

const int PAGE_COUNT = 42; 
    int pageNum = 0; 
    public MainPage() 
    { 
     InitializeComponent(); 
     RefreshImage(); 
    } 

    private void btnPrev_Click(object sender, RoutedEventArgs e) 
    { 
     pageNum = (PAGE_COUNT + pageNum - 1) % PAGE_COUNT; // cycle to prev image 
     RefreshImage(); 
    } 

    private void btnNext_Click(object sender, RoutedEventArgs e) 
    { 
     pageNum = (PAGE_COUNT + pageNum + 1) % PAGE_COUNT; // cycle to next image 
     RefreshImage(); 
    } 

    private void image_Tap(object sender, GestureEventArgs e) 
    { 
     RefreshTextData(); 
    } 

    private void RefreshImage() 
    { 
     BitmapImage image = ImageHolder.Source as BitmapImage; 
     ImageHolder.Source = null; 
     if (image != null) 
     { 
      image.UriSource = null; 
      image = null; 
     } 
     ImageHolder.Source = new BitmapImage(new Uri("000\\image" + (pageNum + 1).ToString("D3") + ".jpg", UriKind.Relative)); 
     RefreshTextData(); 
    } 

    private void RefreshTextData() 
    { 
     MemUsage.Text = "Device Total Memory = " + (long)DeviceExtendedProperties.GetValue("DeviceTotalMemory")/(1024 * 1024) 
      + "\nCurrent Memory Usage = " + (long)DeviceExtendedProperties.GetValue("ApplicationCurrentMemoryUsage")/(1024 * 1024) 
      + "\nPeak Memory Usage = " + (long)DeviceExtendedProperties.GetValue("ApplicationPeakMemoryUsage")/(1024 * 1024); 
    } 

Nhưng vẫn rò rỉ bộ nhớ là có và tôi không thể ghim điểm nó. Tôi đang gặp khó khăn trong việc tìm kiếm nó. Bộ nhớ hồ sơ cho thấy rằng tôi có nhiều trường hợp của một chuỗi, và tôi không thể giải thích điều đó.

Ít điểm:

  • tôi có hình ảnh trong một thư mục "000" và đặt tên là "hình ảnh ###". Hiện tại tôi có hình ảnh có tên tệp từ "image001" đến "image042"
  • Ứng dụng thử nghiệm có dung lượng bộ nhớ 6 MB ngay khi hiển thị trang đầu tiên hoàn toàn bằng hình ảnh và sau khi trang thay đổi tăng lên gần như 18-20 MB
  • Kết quả thay đổi trang tiếp theo khi tăng dần bộ nhớ và sau đó xảy ra sự cố, nếu số lượng hình ảnh cho phép, nếu không sau khi đi xe đạp qua tất cả mức tiêu thụ bộ nhớ hình ảnh là không đổi
  • Tôi đang sử dụng tệp .jpg với kích thước khoảng 1280 x 2000, để thử nghiệm tôi không thay đổi kích thước hình ảnh.

Heap Summary -> New Allocations

+0

Bạn có sinh ra một chuỗi phụ cho mỗi hình ảnh được hiển thị để hiển thị nó không? Bạn có 1918 đối tượng chủ đề xung quanh. Điều đó không có vẻ lành mạnh. Tìm hiểu cách bạn tạo các chủ đề và chấm dứt chúng đúng cách để các tài nguyên liên quan được tham chiếu bằng phương thức thread có thể được phát hành. –

+0

@ Alois, tôi không phải là một chuyên gia, chỉ là một nhà phát triển hobbyist. Tôi thực sự không biết mình đang vô tình tạo chủ đề ở đâu. Tôi không tạo bất kỳ chủ đề nào một cách rõ ràng. Tôi thậm chí không biết, đó thực sự là một vấn đề. Những gì tôi có thể nói rằng những gì bạn đang thấy là toàn bộ mã của ứng dụng mẫu của tôi. Vì vậy, có lẽ nếu bạn có thể tạo lại nó có một cái nhìn vào nó. Sẽ hữu ích. –

Trả lời

5

Tôi có cùng một loại ứng dụng, với các nút hình ảnh trước/sau. Và tôi đã chính xác bị rò rỉ bộ nhớ tương tự, điều đó đã khiến tôi phát điên.

Tôi vẫn chưa tìm được nguyên nhân gốc rễ, nhưng tôi đã xoay xở để vượt qua nó với một bản hack xấu xí.Khi hiển thị hình ảnh tiếp theo, tôi buộc nguồn hình ảnh cũ tải một hình ảnh không hợp lệ, do đó giải phóng bộ nhớ. Tôi không hiểu lý do tại sao loại bỏ tất cả các tài liệu tham khảo và gọi thu gom rác là không đủ, phải có một tài liệu tham khảo được lưu giữ trong một nơi nào đó.

Dù sao, đây là hack:

private void DisposeImage(BitmapImage image) 
{ 
    if (image != null) 
    { 
     try 
     { 
      using (var ms = new MemoryStream(new byte[] { 0x0 })) 
      { 
       image.SetSource(ms); 
      } 
     } 
     catch (Exception) 
     { 
     } 
    } 
} 

Bạn có thể gọi nó là ví dụ trong phương pháp RefreshImage của bạn:

private void RefreshImage() 
{ 
    BitmapImage image = ImageHolder.Source as BitmapImage; 
    ImageHolder.Source = null; 

    DisposeImage(image); 

    ImageHolder.Source = new BitmapImage(new Uri("000\\image" + (pageNum + 1).ToString("D3") + ".jpg", UriKind.Relative)); 
    RefreshTextData(); 
} 

Kinda xấu hổ để sử dụng, nhưng ít nhất nó có vẻ làm việc.

+0

Tôi đã tìm kiếm bạn. Tôi thấy bạn là một trong những thành viên tích cực hơn trong khu vực WP7. SO có thể thiết bị một dịch vụ PM .. Dù sao các giải pháp bạn đề xuất có vẻ là đúng. Bản thân tôi đã nghĩ đến việc đó. Tôi sẽ đánh dấu nó như một câu trả lời, nhưng tôi sẽ không xác nhận nó. Xem câu trả lời của riêng tôi cho điều đó. Nhưng cảm ơn vì đã giúp đỡ. –

1

Tôi đã thử mẫu mã của bạn, nhưng trong Windows Phone 8 môi trường và tôi không thể tái tạo các rò rỉ. Sự khác biệt duy nhất là tôi đã sử dụng hình ảnh của riêng mình.

Mức sử dụng bộ nhớ hiện tại ở mức 13MB đối với Trình mô phỏng 512 WVGA của tôi và Đỉnh ở mức 14MB. Tôi đã đẩy "nút tiếp theo" khoảng 20 lần.

Bạn cũng đã thử sử dụng Bindings cho ImageHolder thay vì đặt nguồn theo cách thủ công chưa?

(btw, trực quan tôi không thấy bất kỳ rò rỉ bộ nhớ nào có thể có trong codebehind của bạn).

(Ngoài ra kiểm tra bài viết này http://blogs.windows.com/windows_phone/b/wpdev/archive/2012/02/01/memory-profiling-for-application-performance.aspx)

+0

"trực quan tôi không thấy bất kỳ rò rỉ bộ nhớ có thể có trong codebehind của bạn"; đó là điều làm tôi khó hiểu. Sẽ cố gắng ràng buộc dữ liệu, nhờ trả lời. –

1

Sau nhiều lần chạy thử và gỡ lỗi, tôi thấy rằng bộ nhớ đệm của hình ảnh này không được thực hiện (hoặc không được thực hiện tích cực) khi hình ảnh đang nằm trong IsolatedStorage của ứng dụng.

Thing là tôi đang sử dụng hình ảnh là một phần của tệp xap, được bao gồm dưới dạng nội dung. Tôi đã làm điều này vì tôi chỉ muốn kiểm tra trình xem hình ảnh của mình. Nhưng điều này sẽ không xảy ra khi ứng dụng của tôi kết thúc. Ứng dụng thực sự được thiết kế để lưu trữ hình ảnh trong bộ nhớ Isolated và hiển thị chúng.

Vì vậy, tôi thiết lập mã và thư thoại cần thiết, Hình ảnh hiện đang nhận được thu thập rác, mặc dù chúng vẫn được lưu trong bộ nhớ cache. Xem hình ảnh bên dưới (xem số lần Garbage Collector được gọi). Đây là một giải pháp cho một câu hỏi không tầm thường, đó là lý do tại sao không ai khác phải đối mặt với vấn đề này.

Tôi tin rằng khi WP7 silverlight phát hiện ra rằng hình ảnh không phải là từ bộ nhớ Isolated, nó giả định hình ảnh từ một số URI từ xa và quyết định lưu vào bộ nhớ cache. Và đó là nơi mà vấn đề bộ nhớ đệm hình ảnh bạc ánh vào. Như một câu trả lời khác xác nhận điều này không xảy ra trong WP8. enter image description here