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

时间:2015-03-13 19:58:09

标签: ios multithreading 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上,我按下暂停按钮,然后队列应该暂停此操作,当我按下start然后它应该从6786开始。

我想控制队列中的多个操作。我怎么能这样做?

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

等待你的答案。

提前致谢!

2 个答案:

答案 0 :(得分: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]

答案 1 :(得分:4)

NSOperation不支持暂停操作,您必须自己实现。这样做的一个策略是使用条件变量(参见Paulw11的答案)。您甚至可以使用单个条件变量来同时控制多个操作。

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

另一种方法是“拆分”操作。因此,当您想要暂停时,首先暂停队列,然后让每个操作将一个新操作对象排入队列,该操作对象从中断处开始。这当然需要更多的参与变化。

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

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

相关问题