gpt4 book ai didi

iphone - 并发和非并发 NSOperations 队列问题

转载 作者:太空狗 更新时间:2023-10-30 03:47:30 25 4
gpt4 key购买 nike

我有一个 NSOperationQueue,它包含 2 个 NSOperations 并设置为通过将 setMaxConcurrentOperationCount 设置为 1 一个接一个地执行它们。

其中一个操作是标准的非并发操作(只是一个 main 方法),它同步地从 Web 检索一些数据(当然是在单独的操作线程上)。另一个操作是并发操作,因为我需要使用一些必须异步运行的代码。

问题是我发现并发操作只有先加入队列才有效。如果它发生在任何非并发操作之后,那么奇怪的是 start 方法被调用得很好,但是在该方法结束并且我已经设置了我的连接以回调方法时,它永远不会。之后不会执行队列中的其他操作。就好像它在 start 方法返回后挂起,并且没有调用任何 url 连接的回调!

如果我的并发操作被放在队列的第一位,那么它一切正常,异步回调工作并且后续操作在它完成后执行。完全不懂!

你可以在下面看到我的并发 NSOperation 的测试代码,我很确定它是可靠的。

任何帮助将不胜感激!

主线程观察:

我刚刚发现,如果并发操作首先在队列中进行,则 [start] 方法会在主线程上被调用。但是,如果它不在队列中的第一个(如果它在并发或非并发之后),则不会在主线程上调用 [start] 方法。这似乎很重要,因为它符合我的问题模式。这可能是什么原因?

并发 NSOperation 代码:

@interface ConcurrentOperation : NSOperation {
BOOL executing;
BOOL finished;
}
- (void)beginOperation;
- (void)completeOperation;
@end

@implementation ConcurrentOperation
- (void)beginOperation {
@try {

// Test async request
NSURLRequest *r = [[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.google.com"]];
NSURLConnection *c = [[NSURLConnection alloc] initWithRequest:r delegate:self];
[r release];

} @catch(NSException * e) {
// Do not rethrow exceptions.
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"Finished loading... %@", connection);
[self completeOperation];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
NSLog(@"Finished with error... %@", error);
[self completeOperation];
}
- (void)dealloc {
[super dealloc];
}
- (id)init {
if (self = [super init]) {

// Set Flags
executing = NO;
finished = NO;

}
return self;
}
- (void)start {

// Main thread? This seems to be an important point
NSLog(@"%@ on main thread", ([NSThread isMainThread] ? @"Is" : @"Not"));

// Check for cancellation
if ([self isCancelled]) {
[self completeOperation];
return;
}

// Executing
[self willChangeValueForKey:@"isExecuting"];
executing = YES;
[self didChangeValueForKey:@"isExecuting"];

// Begin
[self beginOperation];

}

// Complete Operation and Mark as Finished
- (void)completeOperation {
BOOL oldExecuting = executing;
BOOL oldFinished = finished;
if (oldExecuting) [self willChangeValueForKey:@"isExecuting"];
if (!oldFinished) [self willChangeValueForKey:@"isFinished"];
executing = NO;
finished = YES;
if (oldExecuting) [self didChangeValueForKey:@"isExecuting"];
if (!oldFinished) [self didChangeValueForKey:@"isFinished"];
}

// Operation State
- (BOOL)isConcurrent { return YES; }
- (BOOL)isExecuting { return executing; }
- (BOOL)isFinished { return finished; }

@end

排队代码

// Setup Queue
myQueue = [[NSOperationQueue alloc] init];
[myQueue setMaxConcurrentOperationCount:1];

// Non Concurrent Op
NonConcurrentOperation *op1 = [[NonConcurrentOperation alloc] init];
[myQueue addOperation:op1];
[op1 release];

// Concurrent Op
ConcurrentOperation *op2 = [[ConcurrentOperation alloc] init];
[myQueue addOperation:op2];
[op2 release];

最佳答案

我发现问题出在哪里了!

Dave Dribin 的这两篇无价文章非常详细地描述了并发操作,以及 Snow Leopard 和 iPhone SDK 在异步调用需要运行循环的事物时引入的问题。

http://www.dribin.org/dave/blog/archives/2009/05/05/concurrent_operations/ http://www.dribin.org/dave/blog/archives/2009/09/13/snowy_concurrent_operations/

也感谢 Chris Suter 为我指明了正确的方向!

关键是保证我们在主线程调用的start方法:

- (void)start {

if (![NSThread isMainThread]) { // Dave Dribin is a legend!
[self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
return;
}

[self willChangeValueForKey:@"isExecuting"];
_isExecuting = YES;
[self didChangeValueForKey:@"isExecuting"];

// Start asynchronous API

}

关于iphone - 并发和非并发 NSOperations 队列问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1642444/

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