2015-03-13 64 views
0

在我的代码中,我想单独处理队列中的操作,并且能够暂停和恢复队列中的操作操作。我怎样才能实现呢?在单个NSOperationQueue中管理多个操作像暂停/恢复单一操作

让我简单解释一下我的问题,我用下面的代码来创建子类NSOperation的操作,并将此操作添加到NSOperationQueue中。

@interface MyLengthyOperation: NSOperation 
@end 

@implementation MyLengthyOperation 
- (void)main 
{ 
    // a lengthy operation 
    @autoreleasepool 
    { 
     for (int i = 0 ; i < 10000 ; i++) 
     { 

      // is this operation cancelled? 
      if (self.isCancelled) 
      break; 

      NSLog(@"%f", sqrt(i)); 
     } 
    } 
} 
@end 

我上面操作中创建和我与

NSOperationQueue *myQueue = [[NSOperationQueue alloc] init]; 
myQueue.name = @"Download Queue"; 
myQueue.maxConcurrentOperationCount = 4; 
[myQueue addOperation:operation]; 

称它现在我想暂停和恢复我的操作。让我们假设循环是在6786上,然后按下暂停按钮,然后队列应该暂停这个操作,当我按下开始时,它应该从6786开始。

我想控制队列中的多个操作。我怎样才能做到这一点 ?

我看着[queue setSuspended:YES]; - 这将阻止队列添加新的操作,但我想控制队列中的现有操作。

等待您的答案。

在此先感谢!

回答

6

如果你想要这个行为,那么你需要自己构建它,而没有内建的能够暂停某个NSOperation的能力。

您可以使用NSCondition做到这一点 -

@interface MyLengthyOperation: NSOperation 

@property (atomic) BOOL paused; 
@property (nonatomic,strong) NSCondition *pauseCondition; 

@end 

@implementation MyLengthyOperation 

-(instancetype) init { 
    if (self=[super init]) { 
     self.pauseCondition=[NSCondition new]; 
    } 
    return self; 
} 

- (void)main 
{ 
    // a lengthy operation 
    @autoreleasepool 
    { 
     for (int i = 0 ; i < 10000 ; i++) 
     { 

      // is this operation cancelled? 
      if (self.isCancelled) 
      break; 

      [self.pauseCondition lock]; 
      while (self.paused) { 
       [self.pauseCondition wait]; 
      } 
      NSLog(@"%f", sqrt(i)); 
      [self.pauseCondition unlock]; 
     } 
    } 
} 

-(void)pause { 
    [self.pauseCondition lock]; 
    self.paused=YES; 
    [self.pauseCondition signal]; 
    [self.pauseCondition unlock]; 
} 

-(void)resume { 
    [self.pauseCondition lock]; 
    self.paused=NO; 
    [self.pauseCondition signal]; 
    [self.pauseCondition unlock]; 
} 
777441end 

然后你可以说[myOperation pause][myOperation resume]

+2

检查你的答案后,我认为这应该做一个窍门,我一定会尝试上面的代码,希望它会解决我的问题,并非常感谢你@ Paulw11快速和详细的答案。真的很欣赏它! – 2015-03-15 00:50:44

4

NSOperation不提供暂停操作开箱支持,你将不得不实施你自己。一个策略是使用条件变量(请参阅Paulw11的答案)。您甚至可以使用单个条件变量同时控制多个操作。

但是,如果你想暂停许多并发操作,这种方法可能会有问题。每个暂停的操作都会阻塞一个线程。使用条件变量确保那些被阻塞的线程不使用任何CPU,但是这些线程的内存不能被重用。根据暂停线程的数量以及您在此期间想要执行的操作,此内存使用情况可能会有问题。苹果公司将此列为应避免的事情。

另一种方法是“拆分”操作。所以,当你想暂停你首先挂起队列,然后让每个操作排队一个新的操作对象,该对象从停止的地方开始。这当然需要更多的参与改变。

在你的例子中,你会给你的操作子类一个属性firstNumber,并开始你的循环,而不是在零。然后暂停时,您将创建一个新的操作,将当前循环索引作为firstNumber并将其排入队列。

这不仅为您提供了在队列暂停时不阻塞任何线程的优势。而且有了这种可能性,您可以实现一个持久队列,将挂起的操作保存到磁盘,并在下一次应用程序启动时恢复它们。