2012-01-31 6 views
3

コードはかなり簡単です。設定ファイルから既存の画像参照をすべて読み込み、250x250に拡大して別の名前で保存する必要があります。UIImageを別のスレッドのpngとして保存する

問題は、(iPhone 3GとiPadでテストされた)デバイスでは、メモリ警告が表示されてしばらくしてからクラッシュすることです。シミュレータ上では完璧に動作しています。

ThreadPool.QueueUserWorkItem(delegate{ 
    make_thumbs(); 
}); 

make_thumbs機能は次のとおりです:

void make_thumbs() 
{ 
    using(var ns = new NSAutoreleasePool()) 
    { 
     foreach(var c in Settings.Instance.Categories) 
     { 
      for(var i = 0; i < c.Pictures.Count; i++) 
      { 
       //this is the existing bundled image path 
       string  path = c.Pictures[i].PicturePath; 
       string folder = Environment.GetFolderPath(Environment.SpecialFolder.Personal); 
       //this is the destination image file name 
       string filename = Path.Combine(folder, c.Name + i + ".png"); 
       if(!File.Exists(filename)) 
       { 
        NSError err; 
        using(UIImage img = UIImage.FromFile(path).Scale(250,250)) 
        { 
         img.AsPNG().Save(filename, true, out err); 
        } 
       } 
      } 
     } 
    } 
} 
+1

私は問題が何であるか分かりませんが、あなたのコードに適用できるパフォーマンスの微調整があります。 MonoTouchはThreadPoolスレッド用のNSAutoReleasePoolオブジェクトを作成するので、作成する必要はありません。ここでの情報:http://docs.xamarin.com/ios/advanced_topics/threading?highlight=Thread –

+1

完了したらAsPNGの結果を破棄してみてください。最新のMonoDevelop + MonoTouchベータ版では、漏れの原因を突き止めるために使用できるプロファイラもあります。 –

+0

'string folder = Environment.GetFolderPath(Environment.SpecialFolder.Personal);'は不変であり、ループ外に移動する必要があります。 – poupou

答えて

2

Thx @poupou、あなたの答えはほぼ完了しました。私は をforループの内側に(var ns = new NSAutoreleasePool()を使用しなければなりませんでした)。だから、私のコードは今のようにこれは動作しています:

if(!File.Exists(filename)) 
{ 
    using(var ns = new NSAutoreleasePool()) 
    { 
     NSError err; 
     using(UIImage img = UIImage.FromFile(path)) { 
      using (var scaled_img = img.Scale(250,250)) 
      { 
       //i also add a reflection effect        
       using(var reflected_img = scaled_img.AddImageReflection(0.6f)) 
       { 
        using (var data = reflected_img.AsPNG()) 
        { 
         data.Save(filename, true, out err); 
        } 
       } 
      } 
     } 
    } 
} 
4

あなたは(mailing-listから)私の提案を拡張する必要がありますため

私はViewDidAppearにこのコードを持っているのUIViewControllerを持っていますループ内にIDisposableを実装するすべてのもの(GCよりもはるかに素早くメモリを割り当てることができるため、ループを収集することができます)。

@Rolfと同様に、img.AsPNG()NSDataを返します。IDisposableを実装しています。

また、Scaleメソッドを呼び出すと、新しいUIImageが返されます。このブロック、すなわち、全てのメモリを確保するためにカバーする必要があり

using(UIImage img = UIImage.FromFile(path)) { 
    using (var scaled_img = img.Scale(250,250)) { 
     using (var data = img.AsPNG()) { 
      data.Save(filename, true, out err); 
     } 
    } 
} 

は、お使いのデバイス(ないそれらで使用可能なメモリの多くを)助けるべき、できるだけ早く再利用されます。

関連する問題