我正在使用NSOperation
子类(称为PointsOperation)在我的应用程序的后台进行一些计算。由于用户行为,可能需要取消这些计算,并开始新的计算。在这种情况下,我将创建一个新的PointsOperation
实例,并将其添加到与第一个实例相同的NSOperationQueue
。作为PointsOperation主要方法的第一件事,它将检查另一个操作是否已经在运行,并取消它。
因为操作正在使用某些共享缓存,所以它们不能(并且不需要)并行运行。因此,第二个操作将等到第一个操作完成。 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
}
一切正常,第一个操作被取消,第二个等待它完成,然后开始计算。
问题是:在结束主方法的第一个操作与从waitUntilFinished
结束的第二个操作之间需要3-10秒。
有没有人以前见过这个,知道怎么办?
我还尝试使用“addDependency:”(在init方法中,而不是main),而不是waitUntilFinished
,使第二个操作依赖于第一个操作。这也有效,但也有同样的问题:第二个操作的开始是第一个方法完成后的几秒钟。
答案 0 :(得分:0)
尽管名称如此,cancel
方法并没有神奇地取消操作。
取消操作不会立即强制它停止它 是在做。虽然尊重isCancelled返回的值是 期望所有操作,您的代码必须明确检查值 通过此方法返回并根据需要中止。
如果你没有编写代码来检查isCancelled
属性,那么无论你是否取消它,操作的线程都会运行到最后。
答案 1 :(得分: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
这取决于我认为的通话时间。
如果可能的话,也许你应该提供更多的代码,因为问题可能出现在代码的其他地方。