Tri*_*tan 7 c# performance memory-leaks windows-10 uwp
以下使用BitmapDecoder,BitmapPropertySet和BitmapTypedValue会导致本机内存泄漏.我希望我只是错误地使用它们...使用它们的正确方法是什么?它们没有实现IDisposable,所以我不知道如何告诉他们释放他们拥有的本机内存.
这种泄漏有可能无法避免.如果是这样,我将如何保护我的UWP应用程序免受其影响?
Windows性能记录器/分析器的Valloc跟踪显示许多分配,没有Decommit Time.这些对象的提交堆栈表明它们与获取元数据或元数据相关.
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定这是否有助于解决内存问题,但您可以从 StorageFile 本身访问文件的属性,而无需加载到解码器中。
你会这样做:
var systemProperties = new List<string>{ "System.Photo.ShutterSpeed" };
var props = await file.Properties.RetrievePropertiesAsync(systemProperties);
Run Code Online (Sandbox Code Playgroud)
这将返回一个包含您传递的系统属性的字典。您还可以将 null 传递到 RetrievePropertiesAsync 方法,它将返回所有属性,以便您也可以从那里进行筛选。
然后,您可能会像这样从集合中提取数据,具体取决于您想要如何使用该值:
if (props.ContainsKey("System.Photo.ShutterSpeed"))
{
var cameraShutterSpeedObj = props["System.Photo.ShutterSpeed"];
if (cameraShutterSpeedObj != null)
{
var cameraShutterSpeed = cameraShutterSpeedObj.ToString();
}
}
Run Code Online (Sandbox Code Playgroud)
尝试一下,看看是否有任何改进。
归档时间: |
|
查看次数: |
1245 次 |
最近记录: |