mam NSOperationQueue zawierającym 2 NSOperations i ma wykonać je jeden po drugim poprzez ustawienie setMaxConcurrentOperationCount
do 1.Problemy kolejkowania współbieżne i nierównoległymi NSOperations
jedną z operacji, to standardowa operacja nierównoległe (tylko metoda main
), która synchronicznie pobiera niektóre dane z sieci (oczywiście w oddzielnym wątku operacji). Druga operacja jest operacją współbieżną, ponieważ potrzebuję użyć kodu, który musi działać asynchronicznie.
Problem polega na tym, że odkryłem, że operacja współbieżna działa tylko wtedy, gdy jest najpierw dodana do kolejki. Jeśli przychodzi po jakichkolwiek operacjach innych niż współbieżne, to dziwnie, że metoda start
zostaje wywołana dobrze, ale po tym, jak ta metoda się kończy i skonfigurowałem swoje połączenie do wywołania zwrotnego metodą, nigdy tego nie robi. Żadne dalsze operacje w kolejce nie zostaną wykonane później. To tak, jakby zawiesza się po powrocie metody start i nie wywoływane są żadne połączenia zwrotne z jakichkolwiek połączeń URL!
Jeśli moja współbieżna operacja zostanie umieszczona jako pierwsza w kolejce, wszystko działa poprawnie, asynchroniczne wywołania zwrotne działają, a kolejna operacja jest wykonywana po jej zakończeniu. Nie rozumiem w ogóle!
Możesz zobaczyć kod testu dla mojej równoległej NSOperation poniżej, i jestem prawie pewien, że jest solidny.
Każda pomoc będzie bardzo ceniona!
główna Obserwacja Temat:
właśnie odkrył, że jeśli jednoczesne działanie jest pierwszy w kolejce po czym metoda [start]
jest wywoływana w głównym wątku. Jeśli jednak nie jest pierwszym w kolejce (jeśli jest po współbieżnym lub nie współbieżnym), to metoda [start]
nie jest wywoływana w głównym wątku. Wydaje się to ważne, ponieważ pasuje do wzorca mojego problemu. Co mogłoby być tego przyczyną?
Jednoczesne Kod 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
Kod kolejkowania
// 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];
Mam również ten sam problem. Ale w moim przypadku metoda start również nie wymagała czasami nowych operacji. Kolejka nadal pokazuje status "Running". Tak więc powyższej metody nie można użyć. Czy znasz jakieś inne rozwiązanie? Proszę pomóż.. –