performSelectorInBackground无法在iOS5上完成作业

时间:2011-11-14 19:36:36

标签: iphone objective-c ios multithreading

我使用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;
}

2 个答案:

答案 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. 访问调用上下文中定义的局部变量。

  3. 所以,你可以尝试这种方式来看看事情是否有所改善。

答案 1 :(得分:2)

我不会专注于performSelectorInBackground中的更改,而是我会查看你的方法“calculateTotalsWithNumber:”以查看它在iOS5下的行为是否有所不同。如果你的线程偶尔死亡,那么它的实现可能会有一些错误导致死亡。另外,我会在你的项目的其他地方查看是否有其他代码可能会干扰任务。虽然API可能会以一种会导致后台逻辑死亡的方式稍微改变,但我猜不到数百万应用程序使用它的可能性。寻找更有可能发生的事情,例如竞争条件或无保护的iVar,需要通过某种互斥或锁定来保护。