在单个NSOperationQueue中pipe理多个操作,如暂停/恢复单个操作

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

让我简单地解释我的问题,我已经使用下面的代码创build子类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 

我已经创build了上面的操作,我正在调用它

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

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

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

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

等待你的答案。

提前致谢 !

如果你想要这个行为,那么你需要自己构build一个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]

NSOperation不支持暂停操作,你将不得不自己实现。 一个策略是使用一个条件variables(见Paulw11的答案)。 您甚至可以使用单个条件variables同时控制多个操作。

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

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

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

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