gpt4 book ai didi

objective-c - NSOperationQueue 内的 NSOperation 导致应用程序卡住 waitUntilFinished :YES

转载 作者:搜寻专家 更新时间:2023-10-30 20:09:04 25 4
gpt4 key购买 nike

我有 NSOperation 和 AFHTTPClient 请求。在操作结束时,我需要对请求执行另外 N 个操作,并等待请求完成以将主要操作标记为已完成

@interface MyOperation : OBOperation

@end

@implementation MyOperation

- (id)init
{
if (self = [super init]) {
self.state = OBOperationReadyState;
}

return self;
}

- (void)start
{
self.state = OBOperationExecutingState;

AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://google.com"]];
[client getPath:@"/"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSOperationQueue *queue = [NSOperationQueue new];
queue.maxConcurrentOperationCount = 1;

NSMutableArray *ops = [NSMutableArray array];
for (int i = 1; i < 10; i++) {
MyInnerOperation *innerOp = [[MyInnerOperation alloc] initWithNumber:@(i)];
[ops addObject:innerOp];
}

[queue addOperations:ops waitUntilFinished:YES];

self.state = OBOperationFinishedState;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
self.state = OBOperationFinishedState;
NSLog(@"error");
}];
}

@end

链接到问题末尾的 OBOperation 来源。这是一个简单的类,添加了有用的方法来控制 NSOperation

内部操作示例:

@interface MyInnerOperation : OBOperation

- (id)initWithNumber:(NSNumber *)number;

@end

@implementation MyInnerOperation

- (id)initWithNumber:(NSNumber *)number
{
if (self = [super init]) {
_number = number;
self.state = OBOperationReadyState;
}

return self;
}

- (void)start
{
self.state = OBOperationExecutingState;

NSLog(@"begin inner operation: %@", _number);

AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://google.com"]];
[client getPath:@"/"
parameters:nil
success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"inner operation success: %@", _number);
self.state = OBOperationFinishedState;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
self.state = OBOperationFinishedState;
NSLog(@"inner operation error: %@", _number);
}];
}

@end

所以如果我开始我的手术:

MyOperation *op = [MyOperation new];
[_queue addOperation:op];

我在控制台中看到 begin inner operation: 1 就这样!我的应用程序完全卡住(甚至 UI)

经过一些探索后,我确定卡住是由 [queue addOperations:ops waitUntilFinished:YES]; 引起的。如果我不等待完成,我的内部操作会按预期工作,但 MyOperation 会在子操作完成之前完成。

所以现在我有了依赖 block 操作的解决方法:

NSBlockOperation *endOperation = [NSBlockOperation blockOperationWithBlock:^{
self.state = OBOperationFinishedState;
}];

NSMutableArray *ops = [NSMutableArray arrayWithObject:endOperation];
for (int i = 1; i < 10; i++) {
MyInnerOperation *innerOp = [[MyInnerOperation alloc] initWithNumber:@(i)];
[ops addObject:innerOp];

[endOperation addDependency:innerOp];
}

[queue addOperations:ops waitUntilFinished:NO];

但我仍然完全不明白这次卡住的真正问题是什么。任何解释都会非常有用。

OBOperaton 类来源:https://dl.dropboxusercontent.com/u/1999619/issue/OBOperation.h https://dl.dropboxusercontent.com/u/1999619/issue/OBOperation.m

整个项目:https://dl.dropboxusercontent.com/u/1999619/issue/OperationsTest.zip

最佳答案

您陷入僵局的原因是 AFNetworking 将完成 block 分派(dispatch)到主队列。因此,第一个 success 处理程序中的 waitUntilFinished 将阻塞主队列,直到从属请求完成。但是那些从属请求无法完成,因为它们需要将它们的完成 block 分派(dispatch)到主队列,而第一个操作仍在阻塞。

很明显,无论如何你都不想阻塞主队列,但是如果你阻塞主队列等待操作,你就会遇到死锁,而这些操作本身就需要主队列。

关于objective-c - NSOperationQueue 内的 NSOperation 导致应用程序卡住 waitUntilFinished :YES,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23841645/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com