ho un NSOperationQueue che contiene 2 NSOperations ed è impostato per eseguire una dopo l'altra modificando setMaxConcurrentOperationCount
a 1.Problemi Queuing simultanea e non simultanea
Una delle operazioni è un'operazione standard non simultanea (solo un metodo main
) che recupera in modo sincrono alcuni dati dal web (ovviamente sul thread dell'operazione separata). L'altra operazione è un'operazione simultanea in quanto è necessario utilizzare un codice che deve essere eseguito in modo asincrono.
Il problema è che ho scoperto che l'operazione simultanea funziona solo se prima viene aggiunta alla coda. Se viene dopo qualsiasi operazione non simultanea, allora il metodo start
viene chiamato correttamente, ma dopo che il metodo termina e ho impostato la mia connessione a un metodo callback, non lo fa mai. Nessuna ulteriore operazione nella coda viene eseguita dopo. È come se si blocca dopo il ritorno del metodo di avvio, e non vengono richiamati i callback da qualsiasi connessione url!
Se la mia operazione simultanea viene inserita per prima nella coda, tutto funziona correttamente, i callback asincroni funzionano e l'operazione successiva viene eseguita dopo che è stata completata. Non capisco affatto!
È possibile vedere il codice di prova per la mia NSOperation concomitante di seguito, e sono abbastanza sicuro che sia solido.
Qualsiasi aiuto sarebbe molto apprezzato!
principale Osservazione Discussione:
ho appena scoperto che se il funzionamento in parallelo è il primo nella coda quindi il metodo [start]
viene chiamato sul thread principale. Tuttavia, se non è il primo sulla coda (se è dopo un concorrente o non simultaneo), il metodo [start]
non viene chiamato sul thread principale. Questo sembra importante in quanto si adatta allo schema del mio problema. Quale potrebbe essere la ragione di questo?
Concurrent Codice 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
Queuing Codice
// 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];
anche io ho lo stesso problema. Ma nel mio caso, il metodo start non viene anche chiamato per le operazioni appena aggiunte dopo qualche volta. La coda mostra ancora lo stato 'In esecuzione'. Quindi il metodo sopra non può essere usato. Conosci qualche altra soluzione? Per favore aiuto.. –