iOS - 在非主线程上以串行方式运行异步操作

时间:2017-03-28 21:16:19

标签: ios objective-c

- (void) fetchOperation:(NSString *c){
    async_method(c):^{
      NSLog(@"%@ completed.",c);
    }
  }
// call fetchOperation:@"A"
// call fetchOperation:@"B"
// call fetchOperation:@"C"

//Expecting output: A completed, B completed, C Completed.

请注意我希望在非主线程上进行提取。他们可以是1到n次fetchOperation调用。并且每个fetchOperation调用都可能由于用户点击等其他用户操作而发生。 我试过信号量,nsoperationQueue但到目前为止还没有运气。

3 个答案:

答案 0 :(得分:1)

为函数提供一个完成处理程序作为其界面的一部分......

- (void)fetchOperation:(NSString *)string completion:(void(^)(void))completion {
    async_method(string):^{
        NSLog(@"%@ completed.",string);
        if (completion) completion();
    }
}

然后进行嵌套调用......

[self fetchOperation:@"A" completion:^{
    [self fetchOperation:@"B" completion:^{
        [self fetchOperation:@"C" completion:^{
            NSLog(@"all done");
        }];
    }];
}];

编辑要处理任意一组参数,请创建一个接受数组并以递归方式调用自身的函数...

- (void)manyFetchOperations:(NSArray *)parameters completion:(void(^)(void))completion {
    if (!parameters.count) return completion();
    NSString *nextParam = parameters[0];
    NSArray *remainingParams = [parameters subarrayWithRange:NSMakeRange(1, parameters.count-1)];
    [self fetchOperation:nextParam completion:^{
        [self manyFetchOperations:remainingParams completion:completion];
    }];
}

调用它如下,效果与嵌套相同......

[self manyFetchOperations:@[@"A", @"B", @"C"] completion:^{}];

答案 1 :(得分:1)

你尝试过信号量的基本想法听起来不错。

我喜欢使用可扩展方法,您可以轻松扩展正在执行的操作量,从数组中传递所有参数(或其他操作相关信息)。

简单易用的可扩展功能!

- (void)performBatchProcess
{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSArray *attributes = @[@"A", @"B", @"C"];
        NSLog(@"Started all Operations at: %f",CFAbsoluteTimeGetCurrent());
        [self performSelectorWithAttributes:attributes success:^{
            NSLog(@"Finished all Operations");
            NSLog(@"Finished at: %f",CFAbsoluteTimeGetCurrent());
        }];
    });
}

此函数主要用于顺序排队所有操作

- (void)performSelectorWithAttributes:(NSArray<NSString *> *)attributes success:(void (^)())success
{
    for (NSString *attribute in attributes)
    {
        [self performOperationWithAttributeAndWait:attribute];
    }
    success();
}

此基本功能包含在此,其成功块用于停止阻止队列

- (void)performOperationWithAttributeAndWait:(NSString *)attribute
{
    //create a semaphore
    __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);

    void (^privateFinish)(NSString *attribute) = ^(NSString *attribute) {
        NSLog(@"Finished Process: %@",attribute);
        // Stop blocking our thread and go on :-)
        dispatch_semaphore_signal(semaphore);
    };

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"Started Process: %f",CFAbsoluteTimeGetCurrent());
        [NSThread sleepForTimeInterval:2]; // Simulate a process that takes time
        privateFinish(attribute);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
}

示例日志,它表明操作现在至少需要2秒钟(使用计时器模拟过程计算)

2017-03-29 00:05:02.570 asdasd[24376:1836160] Started all Operations at: 512431502.570876
2017-03-29 00:05:02.571 asdasd[24376:1836146] Started Process: 512431502.571429
2017-03-29 00:05:04.598 asdasd[24376:1836146] Finished Process: A
2017-03-29 00:05:04.599 asdasd[24376:1836146] Started Process: 512431504.599392
2017-03-29 00:05:06.673 asdasd[24376:1836146] Finished Process: B
2017-03-29 00:05:06.673 asdasd[24376:1836146] Started Process: 512431506.673433
2017-03-29 00:05:08.673 asdasd[24376:1836146] Finished Process: C
2017-03-29 00:05:08.674 asdasd[24376:1836160] Finished all Operations
2017-03-29 00:05:08.674 asdasd[24376:1836160] Finished at: 512431508.674475

答案 2 :(得分:1)

查看maxconcurrentoperationcount NSOperation属性的文档。

  

可以执行的最大排队操作数   时间。

     

此属性的默认值为   的的NSOperation队列默认最大并发操作计数

将其设置为doc_values应该只根据需要一次运行一个。

编辑:

为了确保您等待另一个完成,您应该查看dependencies

  

此属性包含NSOperation对象的数组。要将对象添加到此数组,请使用add Dependency:方法。   在所有相关操作完成执行之前,操作对象不得执行。 执行完后,不会从此依赖关系列表中删除操作。您可以使用此列表跟踪所有相关操作,包括那些已完成执行的操作。 从此列表中删除操作的唯一方法是使用remove Dependency:方法。

addDependency以及KVO根据您的需要观察isReady1等。

有关上述属性的更多信息和详细信息的良好来源: