j'ai un NSOperationQueue qui contient 2 NSOperations et est placé pour les exécuter l'une après l'autre par la mise setMaxConcurrentOperationCount
à 1.Problèmes simultanés et NSOperations Queueing non simultanées
L'une des opérations est une norme non-fonctionnement simultané (juste une méthode main
) qui récupère de manière synchrone certaines données du web (sur le fil d'opération séparé bien sûr). L'autre opération est une opération simultanée car j'ai besoin d'utiliser du code qui doit s'exécuter de manière asynchrone.
Le problème est que j'ai découvert que l'opération simultanée ne fonctionne que si elle est d'abord ajoutée à la file d'attente. Si elle vient après des opérations non-concurrentes, alors étrangement la méthode start
est appelée bien, mais après que cette méthode se termine et que j'ai configuré ma connexion à callback une méthode, elle ne le fait jamais. Aucune autre opération dans la file d'attente n'est exécutée après. C'est comme si elle se bloque après le retour de la méthode start, et aucun callback de n'importe quelle connexion d'URL n'est appelé!
Si mon opération simultanée est placée en premier dans la file d'attente, tout fonctionne correctement, les callbacks asynchrones fonctionnent et l'opération suivante est exécutée une fois l'opération terminée. Je ne comprends pas du tout!
Vous pouvez voir ci-dessous le code de test de mon NSOperation simultanée, et je suis presque certain qu'il est solide.
Toute aide serait grandement appréciée!
Discussion principale Observation:
Je viens de découvrir que si l'opération simultanée est d'abord sur la file d'attente puis la méthode [start]
est appelée sur le thread principal. Cependant, s'il n'est pas le premier dans la file d'attente (s'il est après un concurrent ou un non-concurrent), la méthode [start]
n'est pas appelée sur le thread principal. Cela semble important car il correspond au modèle de mon problème. Quelle pourrait en être la raison?
simultanées NSOperation code:
@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
code Queueing
// 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];
J'ai aussi eu ce même problème. Mais dans mon cas, la méthode de démarrage ne demande pas non plus de nouvelles opérations après parfois. La file d'attente montre toujours le statut 'Running'. Donc, la méthode ci-dessus ne peut pas être utilisée. Connaissez-vous une autre solution? S'il vous plaît aider .. –