2016-01-17 3 views
7

बिटमैपडेकोडर, बिटमैपप्रॉपर्टीसेट, और बिटमैप टाइपेड वैल्यू के नीचे उपयोग मूल स्मृति में एक रिसाव का कारण बनता है। मुझे आशा है कि मैं बस उन्हें गलत तरीके से उपयोग कर रहा हूं ... उनका उपयोग करने का सही तरीका क्या है? वे IDISposable लागू नहीं करते हैं, इसलिए मुझे यकीन नहीं है कि उन्हें अपनी मूल स्मृति को मुक्त करने के लिए कैसे बताना है।देशी मेमोरी में रिसाव के बिना आप किसी छवि के मेटाडेटा को कैसे एक्सेस करते हैं?

एक मौका है कि इस रिसाव से बचा नहीं जा सकता है। यदि हां, तो मैं अपने यूडब्ल्यूपी ऐप को इसके प्रभाव से कैसे ढाल दूंगा?

विंडोज प्रदर्शन रिकॉर्डर/विश्लेषक से एक वलोक ट्रेस कोई डिकॉमिट टाइम के साथ कई आवंटन दिखाता है। इन वस्तुओं के लिए कमिट स्टैक इंगित करते हैं कि वे मेटाडेटा लाने से संबंधित हैं या मेटाडेटा के टुकड़े हैं।

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; 
     } 
    } 
} 

उत्तर

1

मैं 100% यकीन है कि अगर इस स्मृति मुद्दों के साथ मदद मिलेगी, लेकिन आप विकोडक में लोड किए बिना StorageFile से ही फ़ाइल के गुण का उपयोग कर सकते नहीं कर रहा हूँ।

आप करना चाहते हैं कि इस तरह:

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

यह आपको सिस्टम गुण है कि आप के माध्यम से पारित युक्त एक शब्दकोश वापस आ जाएगी। आप RetrievePropertiesAsync विधि में भी शून्य पास कर सकते हैं और यह सभी गुणों को वापस कर देगा ताकि आप वहां से फ़िल्टर भी कर सकें।

तो आप कैसे आप मूल्य का उपयोग करना चाहते हैं पर निर्भर करता संभवतः इस तरह संग्रह से निकालने होगा:

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

दें कि एक कोशिश और देखो अगर आप किसी भी सुधार देखने।

संबंधित मुद्दे