首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSOperation waitUntilFinished等待了很长时间

NSOperation waitUntilFinished等待了很长时间
EN

Stack Overflow用户
提问于 2012-01-07 00:40:54
回答 2查看 3K关注 0票数 0

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

因为这些操作使用了一些共享缓存,所以它们不能(也不需要)并行运行。因此,第二个操作将等待第一个操作完成。main方法的结果代码如下所示:

代码语言:javascript
复制
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。这也是可行的,但有相同的问题:第二个操作的开始时间比第一个方法的结束时间晚几秒。

EN

回答 2

Stack Overflow用户

发布于 2012-01-07 01:09:46

尽管名为cancel,但它并不能神奇地取消该操作。

取消操作不会立即强制它停止正在执行的操作。尽管所有操作都需要遵守isCancelled返回的值,但您的代码必须显式检查此方法返回的值并在需要时中止。

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

如果您没有编写代码来检查isCancelled属性,则无论您是否取消操作,操作的线程都会运行到最后。

票数 0
EN

Stack Overflow用户

发布于 2012-01-07 11:59:34

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

代码语言:javascript
复制
@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

下面是我如何使用它:

代码语言:javascript
复制
NSOperationQueue* q = [[NSOperationQueue alloc] init];
q.maxConcurrentOperationCount = 4;
for (int i = 0; i < 10; i++) {
    [q addOperation:[PointsOperation new]];
}

waitUntilFinished所用时间的结果分为两类:

代码语言:javascript
复制
After waitUntilFinished took 1.002624 seconds

代码语言:javascript
复制
After waitUntilFinished took 0.000749 seconds

我想这取决于打电话的时间。

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8761223

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档