2010-08-05 30 views
0

我有一个应用程序正在石英上下文绘制线条。当用户在屏幕上移动他的手指时,该应用程序开始绘制。iphone - 主线程冻结了半秒钟......为什么?

当TouchesMoved被触发时,我将Quartz上下文保存到一个PNG文件中(我知道保存文件很慢......我试图对内存执行此操作,但是应用程序内存使用量猛增,所以我试图做到磁盘)。

根据上下文被保存到这一点,我做这在触摸移动

if (firstMove) // first movement after touchesbegan 
    [NSThread detachNewThreadSelector:@selector(newThreadUNDO) 
    toTarget:self 
     withObject:nil]; 
    firstMove = NO 
} 

,然后我有

- (void) newThreadUNDO { 

    NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init]; 

    [NSThread setThreadPriority:0.1]; 

    [NSThread sleepForTimeInterval:0.0]; 
    [self performSelectorOnMainThread:@selector(copyUNDOcontext) withObject:nil waitUntilDone:NO]; 

    [p release]; 
} 

- (void) copyUNDOcontext { 


    CGFloat w = board.image.size.width; 
    CGFloat h = board.image.size.height; 
    CGRect superRect = CGRectMake(0,0, w, h); 

    CGSize size = CGSizeMake(w, h); 

    UIGraphicsBeginImageContext(size); 
    CGContextRef new = UIGraphicsGetCurrentContext(); 
    // lineLayer is the layer context I need to save 
    CGContextDrawLayerInRect(new, superRect, lineLayer); 
    UIImage *imagem = UIGraphicsGetImageFromCurrentImageContext(); 

    [self saveTempImage:imagem :@"UNDO.png"]; 
    UIGraphicsEndImageContext(); 

} 

的问题是:作为一旦用户开始移动,新线程就会被触发,但即使这个新线程的优先级较低,主线程仍然会冻结大约半秒(可能在文件被保存时)。

这是为什么?

我该如何解决这个问题?

谢谢。

回答

1

你试过:

performSelector:onThread:withObject:waitUntilDone: 

随着waitUntilDone设置为NO。

如果我记得正确执行主线程上的选择器总是处理该应用程序的主运行循环中的选择器。我可能是错的。我一直在使用GCD一段时间。

如果您尝试此操作,我相信您需要将autorelease池放入函数中,因为它将用作线程的入口点和退出点。

+0

谢谢!奇迹般有效! – SpaceDog 2010-08-06 11:24:04

+0

很好用。将来你可能想创建一个线程池。这样您就不会重复分配发布池和线程。但是,iOS可能会在后台有一个线程池,将可用(或全局)线程返回给分配。我会在iOS 4上说更多,因为它有GCD。至少你会节省几个CPU周期。 请记住,触摸从另一个线程可可变成一个不舒服的情况。 – 2010-08-06 16:51:32

1

首先,名为saveTempImage::的方法是不鼓励的。使它saveTempImage:fileName:什么的。

你的猜测可能不错,保存文件可能是暂停的来源。如果复杂,也可能是渲染本身,但看起来不像。

但是,猜测通常是分析性能问题的非生产性方式。使用提供的工具。 CPU采样器仪器可以告诉你真正发生了什么。

要解决?首先确认问题。如果是文件I/O,请将其从主线程移出(我没有看过UIImage的文档,以确定它在这种情况下是否是线程安全的)。