【问题标题】:How to ensure FIFO execution in a concurrent NSOperationQueue?如何确保在并发 NSOperationQueue 中执行 FIFO?
【发布时间】:2017-10-01 02:40:43
【问题描述】:

我正在开发一个框架,为了确保非阻塞公共方法,我使用NSOperationQueue 将所有公共方法调用放入操作队列并立即返回。

不同操作之间没有关系或依赖关系,唯一重要的是操作以 FIFO 顺序启动,与它们添加到队列中的顺序相同。

这是我当前实现的一个示例 (sample project here):

@implementation Executor

-(instancetype) init {
    self = [super init];
    if(self) {
        _taskQueue = [[NSOperationQueue alloc] init];
        _taskQueue.name = @"com.d360.tasks";

    }
    return self;
}

-(void) doTask:(NSString*) taskName
{
    NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"executing %@", taskName);
    }];

    [self.taskQueue addOperation:operation];
}

虽然我意识到操作开始的顺序不一定是它们被添加到队列中的顺序。例如,如果我调用

[self.executor doTask:@"Task 1"];
[self.executor doTask:@"Task 2"];

有时Task 2Task 1 之后启动。

问题是如何确保 FIFO 执行开始

我可以使用_taskQueue.maxConcurrentOperationCount = 1; 来实现它,但这一次只允许进行一次我不想要的操作。一个操作不应阻塞任何其他操作,只要它们以正确的顺序启动,它们就可以同时运行。

我还研究了NSOperationQueuePriority 属性,如果我知道我不知道的调用的优先级,它将起作用。事实上,即使我将之前添加的操作发送到NSOperationQueuePriorityHigh,将第二个操作发送到NSOperationQueuePriorityNormal,也不能保证顺序。

[self.executor doTask:@"Task 1" withQueuePriority:NSOperationQueuePriorityHigh];
[self.executor doTask:@"Task 2" withQueuePriority:NSOperationQueuePriorityNormal];

输出有时是

executing Task 2
executing Task 1

有什么想法吗?

谢谢, 一月

【问题讨论】:

  • 您说:“后进先出顺序与它们添加到队列中的顺序相同”。这个说法是矛盾的——你说的是后进先出顺序,但你描述的是先进先出顺序。那么它是什么?
  • 是的,抱歉,它是 FIFO(更新)
  • 您是说一个操作不应阻塞任何其他操作,只要它们以正确的顺序启动,它们就可以同时运行意思是任务是独立的。然后你想要FIFO 排序,最终添加dependency。老实说,FIFO这个概念本身就是一个条件操作。所以只要你的任务是独立的,为什么排序会让人头疼??
  • 有一个执行顺序,not 与一个操作在它的依赖完成 imo 之前无法启动的依赖不同。但我明白你的意思,我应该重新考虑我的设计并在必要时添加依赖项

标签: objective-c nsoperation nsoperationqueue


【解决方案1】:

当您创建每个任务时,您可以使用NSOperation -addDependency 添加对前一个任务的依赖项。复杂之处在于,在依赖任务完成之前,依赖关系不会得到满足,这可能不是您想要的。您可以通过在每个任务中创建另一个 NSOperation 来解决这个问题,并使下一个排队的任务依赖于 that。这个内部任务可以设置一个标志或者说“嘿,我开始了!”的东西。然后,当该内部任务完成时,它将满足队列中下一个任务的依赖关系并允许它启动。

不过,这似乎是一种复杂的做事方式,而且我不确定这样做的好处是否值得额外的复杂性 - 如果它们真的是独立的操作,为什么它们开始的顺序很重要?一旦它们启动,操作系统会决定哪个任务获得 CPU 时间,而且你也没有太多控制权,所以为什么不将它们排队并让操作系统管理启动顺序呢?

【讨论】:

  • 是的,你是对的,这似乎有点矫枉过正。我认为一个解决方案是为订单重要的任务设置一个专用的串行队列。
猜你喜欢
  • 2012-06-12
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-04
  • 2021-04-05
相关资源
最近更新 更多