2016-01-17 12 views
7

Việc sử dụng dưới đây của BitmapDecoder, BitmapPropertySet và BitmapTypedValue gây ra rò rỉ trong bộ nhớ riêng. Tôi hy vọng tôi chỉ sử dụng chúng không chính xác ... Cách chính xác để sử dụng chúng là gì? Họ không thực hiện IDisposable, vì vậy tôi không chắc chắn làm thế nào để nói với họ để phát hành bộ nhớ riêng của họ sở hữu.Làm thế nào để bạn truy cập siêu dữ liệu của hình ảnh mà không gây ra rò rỉ trong bộ nhớ riêng?

Có khả năng không thể tránh rò rỉ này. Nếu vậy, làm thế nào tôi sẽ bảo vệ ứng dụng UWP của tôi khỏi ảnh hưởng của nó?

Dấu vết Valloc từ Trình ghi/phân tích hiệu suất của Windows hiển thị nhiều phân bổ không có thời gian ngừng hoạt động. Ngăn xếp cam kết cho các đối tượng này cho biết chúng có liên quan đến việc tìm nạp siêu dữ liệu hoặc là các phần siêu dữ liệu.

WPR-WPA Valloc trace of running the below test code

using Microsoft.VisualStudio.TestPlatform.UnitTestFramework; 
using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Threading.Tasks; 
using Windows.Graphics.Imaging; 
using Windows.Storage; 
using Windows.Storage.Search; 

namespace Tests 
{ 
    [TestClass] 
    public class TestBitmapDecoderLeak 
    { 
     // Path to a folder containing jpeg's that have metadata. 
     private static readonly string ImageFolderPath = @"path to folder of jpegs"; 

     // The subset of the metadata you want to get 
     private static readonly string [] MetadataPolicies = 
     { 
      "System.Copyright", 
      "System.SimpleRating", 
      "System.Photo.ShutterSpeed", 
      "System.Photo.Aperture", 
      "System.Photo.CameraModel", 
      "System.Photo.CameraManufacturer", 
      "System.Photo.DateTaken", 
      "System.Photo.ExposureTime", 
      "System.Photo.Flash", 
      "System.Photo.FlashEnergy", 
      "System.Photo.ISOSpeed", 
      "System.GPS.Longitude", 
      "System.GPS.Latitude" 
     }; 

     [TestMethod] 
     public async Task RunTest() 
     { 
      // Start your profiler 
      Debugger.Break(); 

      var imageFiles = await GetJpegFiles(); 

      // Get some metadata for each image, but do nothing with it. 
      foreach (var imageFile in imageFiles) 
      { 
       using (var fileStream = await imageFile.OpenReadAsync()) 
       { 
        var decoder = await BitmapDecoder.CreateAsync(fileStream); 

        var DpiX   = decoder.DpiX; 
        var DpiY   = decoder.DpiY; 
        var PixelSizeWidth = decoder.OrientedPixelWidth; 
        var PixelSizeHeight = decoder.OrientedPixelHeight; 
        var DecoderId  = decoder.DecoderInformation.CodecId; 

        var properties = await decoder.BitmapProperties.GetPropertiesAsync(MetadataPolicies); 

        var ShutterSpeed = NullOrValType<double>(properties, "System.Photo.ShutterSpeed"); 
        var Copyright  = NullOrRefType<string>(properties, "System.Copyright"); 
        var SimpleRating = NullOrValType<UInt16>(properties, "System.SimpleRating"); 
        var Aperture  = NullOrValType<double>(properties, "System.Photo.Aperture"); 
        var CameraModel  = NullOrRefType<string>(properties, "System.Photo.CameraModel"); 
        var DateTaken  = NullOrValType<DateTimeOffset>(properties, "System.Photo.DateTaken"); 
        var ExposureTime = NullOrValType<double>(properties, "System.Photo.ExposureTime"); 
        var Flash   = NullOrValType<UInt16>(properties, "System.Photo.Flash"); 
        var FlashEnergy  = NullOrValType<double>(properties, "System.Photo.FlashEnergy"); 
        var IsoSpeed  = NullOrValType<UInt16>(properties, "System.Photo.ISOSpeed"); 
        var Longitude  = NullOrRefType<double[]>(properties, "System.GPS.Longitude"); 
        var Latitude  = NullOrRefType<double[]>(properties, "System.GPS.Latitude"); 
       } 
      } 

      // Remove these so they don't add noise to the trace 
      imageFiles = null; 

      // Ensure everything is cleaned up to the best of the GC's abilities 
      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 

      // Stop your profiler 
      Debugger.Break(); 
     } 

     private static async Task<IEnumerable<StorageFile>> GetJpegFiles() 
     { 
      var folder = await StorageFolder.GetFolderFromPathAsync(ImageFolderPath); 

      var queryOptions = new QueryOptions 
      { 
       FolderDepth = FolderDepth.Deep, 
       IndexerOption = IndexerOption.DoNotUseIndexer, 
      }; 
      queryOptions.FileTypeFilter.Add(".jpg"); 
      queryOptions.FileTypeFilter.Add(".jpeg"); 
      queryOptions.FileTypeFilter.Add(".jpe"); 

      var folderQuery = folder.CreateFileQueryWithOptions(queryOptions); 
      return await folderQuery.GetFilesAsync(); 
     } 

     private static T NullOrRefType<T>(IDictionary<string, BitmapTypedValue> properties, string policy) 
      where T : class 
     { 
      if (properties == null || !properties.ContainsKey(policy)) 
       return null; 

      return (T)properties[policy].Value; 
     } 

     private static T? NullOrValType<T>(IDictionary<string, BitmapTypedValue> properties, string policy) 
      where T : struct 
     { 
      if (properties == null || !properties.ContainsKey(policy)) 
       return null; 

      return (T)properties[policy].Value; 
     } 
    } 
} 

Trả lời

1

Tôi không chắc chắn 100% nếu điều này sẽ giúp với các vấn đề bộ nhớ nhưng bạn có thể truy cập vào thuộc tính của tập tin từ StorageFile bản thân mà không cần phải nạp vào bộ giải mã.

Bạn muốn làm điều đó như thế này:

var systemProperties = new List<string>{ "System.Photo.ShutterSpeed" }; 
var props = await file.Properties.RetrievePropertiesAsync(systemProperties); 

này sẽ đưa bạn trở một từ điển chứa các thuộc tính hệ thống mà bạn đi qua. Bạn cũng có thể truyền null vào phương thức RetrievePropertiesAsync và nó sẽ trả về tất cả các thuộc tính để bạn có thể lọc từ đó.

Sau đó, bạn sẽ trích xuất từ ​​bộ sưu tập có thể như thế này tùy thuộc vào cách bạn muốn sử dụng các giá trị:

if (props.ContainsKey("System.Photo.ShutterSpeed")) 
{ 
    var cameraShutterSpeedObj = props["System.Photo.ShutterSpeed"]; 
    if (cameraShutterSpeedObj != null) 
    { 
     var cameraShutterSpeed = cameraShutterSpeedObj.ToString(); 
    } 
} 

Cho rằng một thử và xem nếu bạn thấy bất kỳ cải tiến.

Các vấn đề liên quan