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

在单个NSOperationQueue iOS中管理多个操作,如暂停/恢复单个操作,ios,multithreading,nsoperationqueue,Ios,Multithreading,Nsoperationqueue,在我的代码中,我希望单独处理队列中的操作,并能够暂停和恢复队列中的操作。我如何实现这一点 让我简单地解释一下我的问题,我使用了下面的代码通过子类NSOperation创建操作,并将此操作添加到NSOperationQueue中 @interface MyLengthyOperation: NSOperation @end @implementation MyLengthyOperation - (void)main { // a lengthy operation @autor

在我的代码中,我希望单独处理队列中的操作,并能够暂停和恢复队列中的操作。我如何实现这一点

让我简单地解释一下我的问题,我使用了下面的代码通过子类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
现在我想暂停并恢复我的操作。假设循环在6786上,我按下了暂停按钮,那么队列应该暂停这个操作,当我按下开始按钮时,它应该从6786开始

我想控制队列中的多个操作。我该怎么做

我看了[队列设置暂停:是];-这将阻止队列添加新操作,但我希望控制队列中的现有操作

等待你的回答


提前谢谢

没有内置暂停特定NSO操作的功能,如果您想要这种行为,则需要自己构建

您可以使用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的答案。您甚至可以使用单个条件变量同时控制多个操作

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

另一种方法是拆分操作。因此,当您想暂停时,首先要挂起队列,然后让每个操作将一个新的操作对象排入队列,从停止的位置开始。当然,这将需要更多涉及的变化

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


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

检查您的答案后,我认为这应该是一个技巧,我一定会尝试上面的代码,希望它能解决我的问题,非常感谢@Paulw11的快速详细回答。真的很感激!
@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