我使用performSelectorInBackground
在后台线程上进行计算,以保持主线程对UI任务的响应。这曾经在iOS4上工作,但似乎在iOS5上引起问题。似乎后台线程有时会成功完成并报告结果,有时它会在没有异常或其他跟踪的情况下静默死亡。
我想知道iOS5中是否有任何更改导致performSelectorInBackground
以不可靠的方式运行?
或者是否有一些我不知道的执行SelectorInBackground的更好的选择?
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;
}
答案 0 :(得分:2)
我不知道iOS 5下的performSelectorInBackground
行为,但在Apple docs中您可以阅读:
performSelectorInBackground:withObject:
在新的后台线程上调用接收器的方法。
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg
参数
aSelector
标识要调用的方法的选择器。该方法不应具有重要的返回值,并且应该采用类型为id的单个参数,或者不带参数。
此外,我只想分享一种使用Grand Central Dispatch以线程方式执行某些代码的替代方法。一个例子可以澄清它的工作方式:
dispatch_queue_t queue = dispatch_get_global_queue(
DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
<your stuff here>
});
您检索全局队列然后向其发送“块”:
^{
<your stuff here>
}
一个块可以看作Objective-C中的“闭包”;在您的情况下,您只需从中调用calculateTotalEarnings
即可。块有两个优点:
匿名函数;
访问调用上下文中定义的局部变量。
所以,你可以尝试这种方式来看看事情是否有所改善。
答案 1 :(得分:2)
我不会专注于performSelectorInBackground中的更改,而是我会查看你的方法“calculateTotalsWithNumber:”以查看它在iOS5下的行为是否有所不同。如果你的线程偶尔死亡,那么它的实现可能会有一些错误导致死亡。另外,我会在你的项目的其他地方查看是否有其他代码可能会干扰任务。虽然API可能会以一种会导致后台逻辑死亡的方式稍微改变,但我猜不到数百万应用程序使用它的可能性。寻找更有可能发生的事情,例如竞争条件或无保护的iVar,需要通过某种互斥或锁定来保护。