c# - Memory consumption of BitmapImage/Image control in Windows Phone 8 -
i testing wp8 app , it's image viewer show many images, found app's memory consumption raising , want find out how solve it.
i've read articles web, solutions provided articles not working on app, please read history below.
first, found article "image tips windows phone 7" , download sample clean image cache testing, it's working 1 image.
and testing purposes, make app compiled 15 offline images inside app, , set "content", please download test app here.
my testing steps are:
(1) launch app (2) go image caching page (3) enable checkbox "avoid image caching" (4) continuously tapping button show/clear (5) keep watching memory status textblock @ bottom when i'm testing app, memory raising, 16.02mb => show(19.32mb) => clear(16.15mb) => show(20.18mb) => clear (17.03mb)...etc , memory won't freed leaving caching page , go caching page again. seems solution of article "image tips windows phone 7" working 1 image.
here comes xaml , code-behind of solution "image tips windows phone 7".
[caching.xaml]
<grid x:name="contentpanel" grid.row="1" margin="12,0,12,0"> <stackpanel orientation="horizontal" verticalalignment="top"> <togglebutton content="show" width="150" checked="showimageclicked" unchecked="clearimageclicked"/> <checkbox x:name="cbavoidcache" content="avoid image caching"/> </stackpanel> <image x:name="img" grid.row="2" width="256" height="192"/> <textblock x:name="tbmemory" grid.row="2" text="memory: " verticalalignment="bottom" style="{staticresource phonetextlargestyle}"/> </grid> [caching.xaml.cs]
public partial class caching : phoneapplicationpage { public caching() { initializecomponent(); dispatchertimer timer = new dispatchertimer(); timer.interval = timespan.frommilliseconds(500); timer.start(); timer.tick += delegate { gc.collect(); tbmemory.text = string.format("memory: {0} bytes", deviceextendedproperties.getvalue("applicationcurrentmemoryusage")); }; } private int nindex = 1; bitmapimage bitmapimagefromuri = new bitmapimage(); private void showimageclicked(object sender, routedeventargs e) { string strimage = string.format("../imagesascontent/{0:d2}.jpg", nindex); bitmapimagefromuri.urisource = new uri(strimage, urikind.relative); img.source = bitmapimagefromuri; nindex++; if (nindex > 15) { nindex = 1; } (sender togglebutton).content = "clear"; } private void clearimageclicked(object sender, routedeventargs e) { if (cbavoidcache.ischecked == true) { // set urisource null in order delete image cache bitmapimage bitmapimagefromuri = img.source bitmapimage; bitmapimagefromuri.urisource = null; } img.source = null; (sender togglebutton).content = "show"; } } i tried search other solutions, testing results below.
(1) article "[wpdev] memory leak bitmapimage": provides 2 solutions, 1 disposeimage api, set bitmapimage source null below. article let know must careful event handler attach/dettach, testing app doesn't have event handler in caching page.
[disposeimage]
private void disposeimage(bitmapimage image) { if (image != null) { try { using (var ms = new memorystream(new byte[] { 0x0 })) { image.setsource(ms); } } catch (exception) { } } } [set null]
bitmapimage bitmapimage = image.source bitmapimage; bitmapimage.urisource = null; image.source = null; (2) article "windows phone: listbox images out-of-memory": provides api "disposeimage" little difference (1)'s below, doesn't work, still got memory raising symptom.
public static void disposeimage(bitmapimage image) { uri uri= new uri("onexone.png", urikind.relative); streamresourceinfo sr=application.getresourcestream(uri); try { using (stream stream=sr.stream) { image.decodepixelwidth=1; //this essential! image.setsource(stream); } } catch {} } (3) article "cannot find memory leak": provides same 2 solutions above mentioned, mentioned issue cannot repro isolated storage's images, testing app's images isolated storage.
(4) tried 1000 images, testing result app crash when app showed around 190 images sequentially, please refer windows phone application analysis graphics memory below. 
finally, patience read question , history, i've been working on find solution many days. if have clue or solution, please kindly let me know.
thanks.
i dealing same problem , think, in end, i've found workaround, not pro programmer here solution:
public task releasesingleimagememorytask(myimage myimage, object control) { pivot mypivot = control pivot; task t = task.factory.startnew(() => { deployment.current.dispatcher.begininvoke(() => { if (myimage.img.urisource != null) { myimage.img.urisource = null; disposeimage(myimage.img); } pivotitem = (pivotitem)(mypivot.itemcontainergenerator.containerfromindex(myimage.number % 10)); image img = findfirstelementinvisualtree<image>(it); if (img != null) { img.source = null; gc.collect(); } }); myimage.released = true; }); return t; } private t findfirstelementinvisualtree<t>(dependencyobject parentelement) t : dependencyobject { var count = visualtreehelper.getchildrencount(parentelement); if (count == 0) return null; (int = 0; < count; i++) { var child = visualtreehelper.getchild(parentelement, i); if (child != null && child t) { return (t)child; } else { var result = findfirstelementinvisualtree<t>(child); if (result != null) return result; } } return null; } private void disposeimage(bitmapimage img) { if (img != null) { try { using (var ms = new memorystream(new byte[] { 0x0 })) { img = new bitmapimage(); img.setsource(ms); } } catch (exception e) { system.diagnostics.debug.writeline("imagedispose failed " + e.message); } } } hope :)
Comments
Post a Comment