我使用performSelectorInBackground
在后台线程上进行计算,以保持主线程对UI任务的响应。这曾经在iOS4上有效,但在iOS5上似乎会出现问题。似乎后台线程有时会成功完成并报告结果,有时它只是无声地死亡,没有异常或其他跟踪。
我想知道iOS5中是否有任何变化导致performSelectorInBackground
以不可靠的方式运行?或者是否有一些更好的替代performSelectorInBackground,我不知道?
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[self.earningsController performSelectorInBackground:@selector(calculateTotalEarnings:) withObject:[NSNumber numberWithInt:_startAmount]];
[pool drain];
-------------------------------------------------------
-(NSDecimalNumber*)calculateTotalEarnings:(NSNumber*)startAmount
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSDecimalNumber *retValue = [NSDecimalNumber zero];
@try
{
retValue = [self calculateTotalsWithNumber:startAmount];
// Post a Notification with calculated totals
[[NSNotificationCenter defaultCenter] postNotificationName:TOTAL_EARNINGS_CALCULATED object:retValue];
}
@catch (NSException * e)
{
NSLog("Exception: %@", [e reason]); // never gets here
}
[pool release];
return retValue;
}
我不会只关注performSelectorInBackground的变化,而是我会看看你的方法"calculateTotalsWithNumber:"看看它在iOS5下的行为是否不同。如果你的线程偶尔死亡,那么在它的实现中可能有一些错误导致死亡。此外,我会看看你的项目的其他地方,看看是否以某种方式另一个代码可以干扰任务。虽然有可能API稍微改变了一点,导致后台逻辑死亡,但我猜这不太可能,因为数百万的应用程序都在使用它。选择一些更有可能的情况,比如竞争条件或需要某种互斥锁或锁来保护的未受保护的iVar。
我不知道iOS 5下performSelectorInBackground
的行为,但在苹果文档中你可以阅读:
performSelectorInBackground: withObject:
在一个新的后台线程上调用接收者的一个方法。
参数
- (void) performSelectorInBackground: (SEL) aSelector withObject: arg (id)
aSelector
标识要调用的方法的选择器。该方法不应该有一个重要的返回值,并且应该接受一个id类型的参数,或者不接受任何参数。
此外,我只是想分享一种使用Grand Central Dispatch以线程方式执行某些代码的替代方法。一个例子可以说明它的工作方式:
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
<your stuff here>
});
检索全局队列,然后向其分派一个"block":
^{
<your stuff here>
}
块可以看作是一个"闭包"。在objective - c中;在您的例子中,您可以简单地从中调用calculateTotalEarnings
。块有两个优点:
匿名函数;
访问在调用上下文中定义的局部变量。
所以,你可以试试这种方法,看看情况是否有所改善。