2010-08-05 55 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的文檔,以確定它在這種情況下是否是線程安全的)。