dan*_*anh 19 objective-c nsoperation nsoperationqueue ios nsblockoperation
我是块的忠实粉丝,但没有将它们用于并发.经过一些谷歌搜索,我拼凑了这个想法,以隐藏我在一个地方学到的一切.目标是在后台执行一个块,当它完成时,执行另一个块(如UIView动画)......
- (NSOperation *)executeBlock:(void (^)(void))block completion:(void (^)(BOOL finished))completion {
NSOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:block];
NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
completion(blockOperation.isFinished);
}];
[completionOperation addDependency:blockOperation];
[[NSOperationQueue mainQueue] addOperation:completionOperation];
NSOperationQueue *backgroundOperationQueue = [[NSOperationQueue alloc] init];
[backgroundOperationQueue addOperation:blockOperation];
return blockOperation;
}
- (void)testIt {
NSMutableString *string = [NSMutableString stringWithString:@"tea"];
NSString *otherString = @"for";
NSOperation *operation = [self executeBlock:^{
NSString *yetAnother = @"two";
[string appendFormat:@" %@ %@", otherString, yetAnother];
} completion:^(BOOL finished) {
// this logs "tea for two"
NSLog(@"%@", string);
}];
NSLog(@"keep this operation so we can cancel it: %@", operation);
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:
谢谢.
nac*_*o4d 19
我不是NSOperation或NSOperationQueues的专家,但我认为下面的代码有点好,虽然我认为它仍有一些警告.可能已经足够用于某些目的但不是并发的通用解决方案:
- (NSOperation *)executeBlock:(void (^)(void))block
inQueue:(NSOperationQueue *)queue
completion:(void (^)(BOOL finished))completion
{
NSOperation *blockOperation = [NSBlockOperation blockOperationWithBlock:block];
NSOperation *completionOperation = [NSBlockOperation blockOperationWithBlock:^{
completion(blockOperation.isFinished);
}];
[completionOperation addDependency:blockOperation];
[[NSOperationQueue currentQueue] addOperation:completionOperation];
[queue addOperation:blockOperation];
return blockOperation;
}
Run Code Online (Sandbox Code Playgroud)
现在让我们使用它:
- (void)tryIt
{
// Create and configure the queue to enqueue your operations
backgroundOperationQueue = [[NSOperationQueue alloc] init];
// Prepare needed data to use in the operation
NSMutableString *string = [NSMutableString stringWithString:@"tea"];
NSString *otherString = @"for";
// Create and enqueue an operation using the previous method
NSOperation *operation = [self executeBlock:^{
NSString *yetAnother = @"two";
[string appendFormat:@" %@ %@", otherString, yetAnother];
}
inQueue:backgroundOperationQueue
completion:^(BOOL finished) {
// this logs "tea for two"
NSLog(@"%@", string);
}];
// Keep the operation for later uses
// Later uses include cancellation ...
[operation cancel];
}
Run Code Online (Sandbox Code Playgroud)
您的问题的一些答案:
取消.通常你是NSOperation的子类,所以你可以先检查self.isCancelled
并返回.看到这个帖子,这是一个很好的例子.在当前示例中,您无法检查是否已从要提供的块中取消操作,NSBlockOperation
因为此时尚未执行此类操作.NSBlockOperation
在调用块时取消s显然是可能的但是很麻烦.NSBlockOperation
s适用于特定的简单案例.如果您需要取消,您可以更好地继承NSOperation
:)
我这里没有看到问题.虽然注意两件事.a)我更改了方法do以在当前队列中运行完成块b)需要队列作为参数.正如@Mike Weller所说,你应该更好地供应,background queue
这样你就不需要为每个操作创建一个,并且可以选择用来运行你的东西的队列:)
我想是的,你应该做string
atomic
.你不应该忘记的一件事是,如果你向队列提供了几个操作,它们可能不会按顺序运行(必然),所以你最终可能会收到一条非常奇怪的消息string
.如果您需要连续一次运行一个操作,则可以执行以下[backgroundOperation setMaxConcurrentOperationCount:1];
操作:在开始排队操作之前.虽然文档中有一个值得阅读的注释:
其他操作队列行为 操作队列根据其优先级和准备情况执行其排队的操作对象.如果所有排队的操作对象具有相同的优先级并且在将它们放入队列时准备好执行 - 也就是说,它们的isReady方法返回YES-它们按照它们被提交到队列的顺序执行.对于最大并发操作数设置为1的队列,这相当于一个串行队列.但是,您永远不应该依赖于操作对象的串行执行.操作就绪的更改可以更改生成的执行顺序.
我想在看完这些线后你知道:)
您不应该NSOperationQueue
为每个executeBlock:completion:
呼叫创建新的.这很昂贵,并且此API的用户无法控制一次可执行的操作数.
如果要返回NSOperation
实例,则应将其留给调用者以决定将其添加到哪个队列.但在那时,你的方法确实没有做任何有用的事情,调用者也可以NSBlockOperation
自己创建.
如果你只是想要一个简单易用的方法来在背景中分割一个块并在它完成时执行一些代码,你可能最好用dispatch_*
函数做一些简单的GCD调用.例如:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// do your background work
// ...
// now execute the 'completion' code.
// you often want to dispatch back to the main thread to update the UI
// For example:
dispatch_async(dispatch_get_main_queue(), ^{
// update UI, etc.
myLabel.text = @"Finished";
});
});
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
16173 次 |
最近记录: |