Отправка изменяемых данных через границы потоков - хороший способ решения проблем. Вы должны всегда использовать NSArray
, NSString
, NSSSet
и т. Д. Вместо их изменяемого подкласса при отправке объекта в другой поток. Это простое правило делает многопоточность намного приятнее.
К счастью, все классы коллекции реализуют протокол NSCopying
и, таким образом, имеют отличный метод -[copy]
, который возвращает неизменную копию самого себя.
Следующее, что вам нужно решить, это что делать, если вы изменяете исходный массив. Не могли бы вы:
- Просто поставить в очередь новую операцию поиска пути?
- Отменить текущую операцию поиска пути и начать новую?
Вариант 1. Просто добавить новую операцию проще всего, но может / будет тратить время, если ваши исходные массивы часто видоизменяются.
Вариант 2. требует дополнительной работы с вашей стороны. Более конкретно:
- Вы должны удержать последнюю операцию, чтобы отправить ей сообщение
-[NSOperation cancel]
. Или, если у вас есть очередь, предназначенная только для поиска пути, вы можете отменить все операции над ней, используя [NSOperationQueue cancelAllOperations]
.
- Вы должны выйти из операции на ранней стадии, если она будет отменена. Это требует от вас подкласса
NSOperation
, вы больше не можете просто использовать NSInvocationOperation
как есть.
Ваша реализация подкласса NSOperation
должна выглядеть примерно так:
@implementation CWPathfinderOperation
-(id)initWithFiends:(NSArray*)fiends delegate:(id<CWPathfinderOperation>)delegate {
self = [super init];
if (self) {
self.fiends = fiends;
self.delegate = delegate;
}
return self;
}
-(void)main {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
while (notDone) {
if ([self isCancelled]) goto bailOut;
// Do smallpart of work
}
[self.delegate performSelectorOnMainThread:@selector(pathfinderOperatioDidFindPaths:)
withObject:result
waitUntilDone:NO];
bailOut:
[pool release];
}
@end