[英]iOS - Run async operations in serial manner on non-main thread
- (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,但到目前为止还没有运气。
给函数一个完成处理程序作为其接口的一部分...
- (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:^{}];
您尝试过信号灯的基本想法听起来不错。
我喜欢使用可扩展方法,您可以在其中轻松扩展正在执行的操作量,并在其中传递数组中的所有参数(或其他与操作相关的信息)。
简单易扩展的功能!
- (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
检查出的文档maxconcurrentoperationcount财产的NSOperation 。
可以同时执行的最大排队操作数。
此属性的默认值为NSOperationQueue默认最大并发操作数 。
将其设置为1
只能一次运行一次。
编辑:
为了确保您等待其他人完成,您应该查看依赖项
此属性包含NSOperation对象的数组。 要将对象添加到此数组,请使用addDependency:方法。 直到其所有相关操作完成执行后,操作对象才可以执行。 操作完成执行后,不会从此依赖项列表中删除操作 。 您可以使用此列表来跟踪所有相关的操作,包括已经完成执行的操作。 从此列表中删除操作的唯一方法是使用removeDependency:方法。
并根据需要isFinished
addDependency和KVO观察isReady 。
有关上述属性的更多信息和详细信息的良好来源:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.