在单个NSOperationQueue中管理多个操作像暂停/恢复单一操作
在我的代码中,我想单独处理队列中的操作,并且能够暂停和恢复队列中的操作操作。我怎样才能实现呢?在单个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];
- 这将阻止队列添加新的操作,但我想控制队列中的现有操作。
等待您的答案。
在此先感谢!
如果你想要这个行为,那么你需要自己构建它,而没有内建的能够暂停某个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
不提供暂停操作开箱支持,你将不得不实施你自己。一个策略是使用条件变量(请参阅Paulw11的答案)。您甚至可以使用单个条件变量同时控制多个操作。
但是,如果你想暂停许多并发操作,这种方法可能会有问题。每个暂停的操作都会阻塞一个线程。使用条件变量确保那些被阻塞的线程不使用任何CPU,但是这些线程的内存不能被重用。根据暂停线程的数量以及您在此期间想要执行的操作,此内存使用情况可能会有问题。苹果公司将此列为应避免的事情。
另一种方法是“拆分”操作。所以,当你想暂停你首先挂起队列,然后让每个操作排队一个新的操作对象,该对象从停止的地方开始。这当然需要更多的参与改变。
在你的例子中,你会给你的操作子类一个属性firstNumber
,并开始你的循环,而不是在零。然后暂停时,您将创建一个新的操作,将当前循环索引作为firstNumber并将其排入队列。
这不仅为您提供了在队列暂停时不阻塞任何线程的优势。而且有了这种可能性,您可以实现一个持久队列,将挂起的操作保存到磁盘,并在下一次应用程序启动时恢复它们。
检查你的答案后,我认为这应该做一个窍门,我一定会尝试上面的代码,希望它会解决我的问题,并非常感谢你@ Paulw11快速和详细的答案。真的很欣赏它! – 2015-03-15 00:50:44