我正在使用NSOperation子类(称为PointsOperation)在我的应用程序的后台执行一些计算。由于用户行为,这些计算可能需要取消,并开始新的计算。在这种情况下,我将创建一个新的PointsOperation实例,并将其添加到与第一个实例相同的NSOperationQueue中。作为PointsOperation的main方法中的第一件事,它将检查另一个操作是否已经在运行,并取消该操作。
因为这些操作使用了一些共享缓存,所以它们不能(也不需要)并行运行。因此,第二个操作将等待第一个操作完成。main方法的结果代码如下所示:
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
}这一切都很好,第一个操作被取消,第二个操作等待它完成,然后开始计算。
问题是:第一次操作结束main方法,第二次操作从waitUntilFinished结束,需要3-10秒。
有没有人以前见过这种情况,知道该怎么做?
我还尝试使用"addDependency:“(在waitUntilFinished方法中,而不是main方法中)使第二个操作依赖于第一个操作,而不是main。这也是可行的,但有相同的问题:第二个操作的开始时间比第一个方法的结束时间晚几秒。
发布于 2012-01-07 01:09:46
尽管名为cancel,但它并不能神奇地取消该操作。
取消操作不会立即强制它停止正在执行的操作。尽管所有操作都需要遵守isCancelled返回的值,但您的代码必须显式检查此方法返回的值并在需要时中止。
http://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html
如果您没有编写代码来检查isCancelled属性,则无论您是否取消操作,操作的线程都会运行到最后。
发布于 2012-01-07 11:59:34
我试图在这里重现这个问题,但我的代码工作正常,没有这样的延迟。这是我的代码:
@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我想这取决于打电话的时间。
如果可能的话,也许你应该提供更多的代码,因为问题可能在你的代码中的其他地方。
https://stackoverflow.com/questions/8761223
复制相似问题