- (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但到目前为止还没有运气。
答案 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根据您的需要观察isReady,1
等。
有关上述属性的更多信息和详细信息的良好来源:
Tutorial(由Mattt提供)