以下のコードを使用して、UI要素に基づいてライブタイルを作成しています。をレンダリングしuiElement
、WriteableBitmap
ビットマップを保存し、ファイル名を返します。このメソッドは、WindowsPhoneのバックグラウンドタスクエージェントで実行されます。メモリ制限が発生しています。
private string CreateLiveTileImage(Canvas uiElement, int width, int heigth)
{
var wbmp = new WriteableBitmap(width, heigth);
try
{
wbmp.Render(uiElement, null);
wbmp.Invalidate();
var tileImageName = _liveTileStoreLocation;
using (var stream = new IsolatedStorageFileStream(tileImageName, FileMode.Create, FileAccess.Write, IsolatedStorageFile.GetUserStoreForApplication()))
{
wbmp.SaveJpeg(stream, width, heigth, 0, 100);
stream.Close();
}
uiElement = null;
wbmp = null;
GC.Collect();
return "isostore:" + tileImageName;
}
catch (Exception exception)
{
// ...
}
return null;
}
私はいくつかのテストを行いましたが、問題は次のとおりです。このメソッドはメモリをリークしますが、理由/場所がわかりません。
また、このメソッドを最初に実行する前に、いくつかのテストを実行しました。
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
7.249.920 Bytes
デバッガーが接続されているため、これは問題ありません。デバッガーは約2MBのメモリを使用します。
このメソッドをさらに実行する(デバッガーでメソッドを再度実行するように設定し直す):
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
8851456 long + 40960
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
8892416 long + 245760
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9138176 long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9281536 long + 151552
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9433088 long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9576448 long + 139264
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9715712 long + 139264
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
9859072 long + 143360
Microsoft.Phone.Info.DeviceStatus.ApplicationCurrentMemoryUsage
10006528 long + 147456
したがって、このメソッドで使用されるメモリが増加します。
しかし、なぜ?私の意見では、オブジェクトの収集を妨げる参照はありません。
2013年5月4日の更新
やあ、
すべての回答ありがとうございます!提案されたように、私はコードを減らしました+最終的に数行のコードで問題を再現することができました。
void Main()
{
for (int i = 0; i < 100; i++)
{
CreateImage();
}
}
private void CreateImage()
{
var rectangle = CreateRectangle();
var writeableBitmap = new WriteableBitmap(rectangle, rectangle.RenderTransform);
rectangle = null;
writeableBitmap = null;
GC.Collect();
}
private Rectangle CreateRectangle()
{
var solidColorBrush = new SolidColorBrush(Colors.Blue);
var rectangle = new Rectangle
{
Width = 1000,
Height = 1000,
Fill = solidColorBrush // !!! THIS causes that the image writeableBitmap never gets garbage collected
};
return rectangle;
}
アプリを起動した後:ApplicationCurrentMemoryUsage: "11681792バイト"
1回の反復-ApplicationCurrentMemoryUsage: "28090368バイト"
5回の反復-ApplicationCurrentMemoryUsage: "77 111 296 Bytes"
20回の反復-ApplicationCurrentMemoryUsage: "260 378 624 Bytes"
23回の反復後:メモリ不足の例外。 Ln .: var writeableBitmap = new WriteableBitmap(rectangle、rectangle.RenderTransform);
「Fill=solidColorBrush」の行をコメントアウトするだけで、CreateImage()メソッドは問題なく100回呼び出されました。100回目の反復後、メモリ使用量は約「16064512バイト」でした。
だから問題はブラシだと思います!! UI要素を埋めるために使用され、後でこのUI要素が書き込み可能なビットマップにレンダリングされると、ビットマップがガベージコレクションされることはありません。
もちろん、これは私の意見では意味がありません。ブラシが範囲外になるので、ガベージコレクションも行う必要があります。(使用後にブラシをnullに設定しても、何も変更されませんでした)
私のUI要素の多くは塗りつぶしにブラシを使用しているため、ブラシの使用を単純に削除することはできません。この問題についてどう思いますか?