NSOperationQueue串行FIFO队列(NSOperationQueue serial F

2019-06-25 08:53发布

是否有可能使用NSoperationQueue其设置对象为串行FIFO队列maxConcurrentOperationCount为1?

我注意到, 文档状态...

对于一个队列,其并发操作的最大数量设置为1,这相当于一个串行队列。 但是,你不应该依赖于操作对象的串行执行。

这是否意味着FIFO执行不保证?

Answer 1:

在大多数情况下,这将是FIFO。 但是,您可以建立依赖性NSOperations之间,使得年初提交的操作将让其他运营方式传递的队列中,直到其依赖性得到满足。

这种依赖关系管理就是为什么文档表明,FIFO岬不能得到保证。 如果你不使用的依赖,但是,你应该罚款依靠它。

更新 :的NSOperation也有queuePriority属性,它也可能导致操作在非FIFO的顺序执行。 没有未决的依赖关系的优先级最高的操作将始终首先执行。

一个子类的NSOperation也可能会覆盖-isReady ,这可能导致其移回队列中。

所以,在你的队列执行是保证连续 ,在不超过一个操作将在这个队列中的时间运行。 但是,苹果不能保证FIFO; 这取决于你和你把作业做什么。



Answer 2:

如由文档中提到的队列没有FIFO。 你可以把它严格的FIFO,如果你确保任何新的操作取决于在队列最后添加的操作,它只能同时运行一个操作。 奥马尔的解决方案是正确的,但更普遍的,你可以做到以下几点:

NSOperationQueue* queue = [[ NSOperationQueue alloc ] init];
queue.maxConcurrentOperationCount = 1;

NSOperation* someOperation = [ NSBlockOperation blockOperationWithBlock:^(void) { NSLog(@"Done.");} ];

if ( queue.operations.count != 0 )
    [ someOperation addDependency: queue.operations.lastObject ];

这工作,因为queue.operations是一个数组:无论你加不重新排序(它不是实例的NSSet)。 你也可以简单的类别添加到您的NSOperationQueue:

@interface NSOperationQueue (FIFOQueue)
- (void) addOperationAfterLast:(NSOperation *)op;
@end

@implementation NSOperationQueue (FIFOQueue)

- (void) addOperationAfterLast:(NSOperation *)op
{
    if ( self.maxConcurrentOperationCount != 1)
        self.maxConcurrentOperationCount = 1;

    NSOperation* lastOp = self.operations.lastObject;
    if ( lastOp != nil )
        [ op addDependency: lastOp ];

    [ self addOperation:op];
}

@end

并使用[队列addOperationAfterLast:myOperation]。 queuePriority无关与FIFO,它关系到作业调度。

编辑:按照下面的注释,暂停队列,如果检查的次数也不够。 我相信,这种形式很好(在测试时,这不会产生竞争条件,并不会崩溃)。

一些信息: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperationQueue_class/#//apple_ref/occ/instp/NSOperationQueue/suspended



Answer 3:

要使用nsInvocationopration做一个简单的FIFO,您将需要设置一个操作上的其他应用addDependency将取决于:方法

NSOperationQueue *queue = [[NSOperationQueue alloc] init];
NSInvocationOperation *oper1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"1"];

NSInvocationOperation *oper2 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"2"];
NSInvocationOperation *oper3 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(doSth:) object:@"3"];

[oper2 addDependency:oper1];
[oper3 addDependency:oper2];
//oper3 depends on oper2 wich depends on oper1
//order of execution will ber oper1->oper2->oper3

//Changing the oreder will not change the result
[queue addOperation:oper2];
[queue addOperation:oper3];
[queue addOperation:oper1];


- (void) doSth:(NSString*)str
{
    NSLog(str); //log will be 1 2 3
    //When you remove the addDependency calls, the logging result that i got where
    //different between consecutive runs i got the following
    //NSLog(str); //log will be 2 1 3
    //NSLog(str); //log will be 3 1 2
}

:如果您使用NSInvocationOperation然后设置maxConcurrentOperationCount 1将最有可能做的伎俩给你,因为的isReady不会被你编辑

maxConcurrentOperationCount = 1就不会是一个很好的解决方案,如果你是刨去创建自己的子类NSOperation

由于的NSOperation衍生工具,你可以重写isReady功能和返回无,(想象一下一些操作,将需要从服务器的一些数据等待才能正常工作),在这些情况下,您将返回isReady no ,直到你真的准备好了在这些情况下,你将需要添加dependencies之间operations的队列中

从苹果公司的文档,这相当于一个串行队列。 但是,你不应该依赖于操作对象的串行执行。 在操作的准备就绪的变化可改变所得的执行顺序



文章来源: NSOperationQueue serial FIFO queue