将UIImage保存为另一个线程的png

时间:2012-01-31 09:01:49

标签: c# multithreading xamarin.ios uiimage

代码非常简单,它必须从设置文件加载所有现有图像引用,将它们缩放到250x250并用另一个名称保存它们。

问题是在设备上(在iPhone 3g和iPad上测试)它会在一段时间后因内存警告而崩溃。在模拟器上,它的工作非常完美。

我有一个UIViewController,它在ViewDidAppear上有这段代码:

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

2 个答案:

答案 0 :(得分:4)

你需要扩展我的建议(来自mailing-list),以便在你的循环中实现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 );
         }
     }
 }

这应该涵盖这个块,即确保尽快回收所有内存,这应该有助于你的设备(不是很多内存可用)。

答案 1 :(得分: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 );
                    }
                }
             }
        }
    }
}