2012-01-06 69 views
0

我正在使用NSOperation子类(称为PointsOperation)在我的应用程序的后台执行一些计算。由于用户的行为,这些计算可能需要取消,并开始新的计算。在这种情况下,我将创建一个新的PointsOperation实例,并将其作为第一个添加到相同的NSOperationQueue。作为PointsOperation的主要方法中的第一件事,它将检查另一个操作是否已在运行,并取消它。NSOperation waitUntilFinished等待很长时间

因为这些操作正在使用某些共享缓存,所以它们不能(并且不需要)并行运行。因此,第二个操作将等到第一个操作完成。主方法生成的代码看起来是这样的:

static NSOperation *currentOperation = nil; 
- (void) main 
{ 
    // setting up autorelease pool, catching exceptions, etc 
    @synchronized(lock) { 
     if (currentOperation != nil) { 
     [currentOperation cancel]; 
     [currentOperation waitUntilFinished]; 
     } 
     currentOperation = self; 
    } 
    while (!calculationsFinished && ![self isCancelled]) { 
     // do calculations 
    } 
    currentOperation = nil; 
    // releasing autorelease pool, etc 
} 

这一切工作正常,第一个操作被取消,并为它完成第二等待,然后开始计算。

问题是:在结束主要方法的第一个操作和从waitUntilFinished出来的第二个操作之间需要3-10秒。

有没有人看过这个,知道该怎么办?

我也试过,而不是waitUntilFinished,使第二个操作依赖于第一个,与“addDependency:”(在init方法,而不是主)。这也适用,但也有同样的问题:第二个操作的开始是第一个方法完成后的秒数。

回答

0

尽管它的名字,cancel方法不会奇迹般地取消操作。

取消操作并不会立即强制停止它正在执行的操作。虽然尊重isCancelled返回的值是所有操作的预期值 ,但您的代码必须明确检查此方法返回的值 并根据需要中止。

http://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html

如果你没有写你的代码来检查isCancelled财产,所以操作的线程将运行到结束,不管你取消与否。

+0

感谢您的回答。正如你在上面的代码和描述中看到的,我确实检查了isCancelled。另外,我使用NSLog语句验证了操作因取消而完成,并且延迟肯定在第一个操作的主方法结束和waitUntilFinished出来的第二个操作之间。 – fishinear 2012-01-06 17:18:17

+0

@fishinear对不起,我错过了:( – tia 2012-01-06 17:20:36

+0

并不意味着唠叨你,但我注意到你拼写错了'[currentOparation waitUntilFinished]'这行变量,仍然得到它编译? – tia 2012-01-06 17:31:38

0

我试图在这里重现问题,但我的代码工作正常,没有这样的延迟。这是我的代码:

@interface PointsOperation : NSOperation { 
@private 
    bool calculationsFinished; 
} 

@property (nonatomic, assign) int tag; 

@end 


@implementation PointsOperation 

@synthesize tag; 

static NSOperation *currentOperation = nil; 
static NSString* lock = @"LOCK"; 

- (void) main 
{ 
    NSLog(@"Before autoreleasepool with tag: %d", tag); 
    @autoreleasepool { 
     NSLog(@"Before lock"); 
     // setting up autorelease pool, catching exceptions, etc 
     @synchronized(lock) { 
      if (currentOperation != nil) { 
       NSLog(@"Before cancel"); 
       [currentOperation cancel]; 
       NSLog(@"Before waitUntilFinished"); 
       NSDate* beforeWait = [NSDate date]; 
       [currentOperation waitUntilFinished]; 
       NSLog(@"After waitUntilFinished took %f seconds", [[NSDate date] timeIntervalSinceDate:beforeWait]);     
      } 
      currentOperation = self; 
     } 
     NSLog(@"Before while loop"); 
     int i = 0; 
     while (!calculationsFinished && ![self isCancelled]) { 
      // do calculations 
      [NSThread sleepForTimeInterval:1]; 
      NSLog(@"Inside while loop = %d", i); 
      calculationsFinished = (++i > 10); 
     } 
     NSLog(@"After while loop: i = %d", i); 
     currentOperation = nil; 
     // releasing autorelease pool, etc 
    } 
    NSLog(@"%@", @"End of method"); 
} 

@end 

下面是我如何使用它:

NSOperationQueue* q = [[NSOperationQueue alloc] init]; 
q.maxConcurrentOperationCount = 4; 
for (int i = 0; i < 10; i++) { 
    [q addOperation:[PointsOperation new]]; 
} 

的时间,结果把通过waitUntilFinished进来两类:

After waitUntilFinished took 1.002624 seconds 

After waitUntilFinished took 0.000749 seconds 

这取决于我认为电话的时间安排。

也许你应该提供更多的代码,如果可能的话,因为问题可能在你的代码中的其他地方。

相关问题