Опасно ли запускать автоматически выпущенный NSOperationQueue?

У меня есть задача, которая занимает довольно много времени и должна выполняться в фоновом режиме. Согласно документации, это можно сделать с помощью файла NSOperationQueue. Однако я не хочу хранить глобальную копию класса NSOperationQueue, так как я действительно использую ее только для этой одной задачи. Следовательно, я просто установил для него автоматический выпуск и надеюсь, что он не будет выпущен до того, как задача будет выполнена. Это работает.
вот так:

NSInvocationOperation *theTask = [NSInvocationOperation alloc];
theTask = [theTask initWithTarget:self
                         selector:@selector(doTask:)
                           object:nil];
NSOperationQueue *operationQueue = [[NSOperationQueue new] autorelease];
[operationQueue addOperation:theTask];
[theTask release];

Хотя я как-то беспокоюсь. Это гарантированно работает? Или может быть operationQueue в какой-то момент освободится и заберет с собой theTask?


person bastibe    schedule 23.03.2010    source источник
comment
Не уверен в ответе, но [NSOperationQueue new] возвращает автоматически выпущенный объект, поэтому [[NSOperationQueue new] autorelease] заставит вас дважды выпускать в одной и той же очереди и должен привести к сбою. Кроме того, всегда и всегда делайте [[Class alloc] init...] вложенными. Никогда не разделяйте alloc и init. Вы избавите себя от головной боли.   -  person Johan Kool    schedule 23.03.2010
comment
[NSObject new] эквивалентен [[NSObject alloc] init], поэтому не выпускается автоматически...   -  person dstnbrkr    schedule 23.03.2010
comment
Это не тот ответ, который вы ищете, но поскольку он вам нужен только для одной задачи, это [self performSelectorInBackground:@selector(doTask:) withObject:nil] вариант. Или это должна быть NSOperation?   -  person Brandon Bodnar    schedule 23.03.2010
comment
@Brandon_Bodnar: звучит здорово, но по какой-то причине мое приложение задыхается.   -  person bastibe    schedule 23.03.2010
comment
Как насчет того, чтобы не освобождать очередь автоматически, а вместо этого добавить еще одну задачу в конец очереди, которая ее освобождает?   -  person Nick Moore    schedule 24.03.2010
comment
@invariant, это интересная идея!   -  person bastibe    schedule 24.03.2010


Ответы (4)


В документации ничего не говорится о том, что происходит при выпуске NSOperationQueue. Было бы безопаснее предположить, что нет никакой гарантии, что задача будет выполнена.

person Nick Moore    schedule 23.03.2010

Я бы предположил, что NSOperationQueue освобождает свои задачи при освобождении, но я заметил, что задачи завершаются и освобождаются, даже если я освобождаю очередь сразу после добавления задачи. Тем не менее, я не думаю, что стал бы полагаться на такое поведение - можно получить больше, сохранив NSOperationQueue в переменной экземпляра (и выпустив ее в Dealloc). Переменная экземпляра даст вам возможность вызывать другие методы в очереди (cancelAllOperations, setSuspended и т. д.).

person dstnbrkr    schedule 23.03.2010
comment
нет никакого дальнейшего взаимодействия, которое я хотел бы сделать. Это даже не было бы большой проблемой, если бы задача вообще не завершилась (фоновое изображение выглядело бы слегка нечетким, вот что произошло бы). - person bastibe; 23.03.2010
comment
вероятно, не опасно освобождать очередь в этом случае, с оговоркой, что, поскольку нет никакой документации, нет гарантии, что она не будет работать по-другому в более поздних версиях SDK. Я предполагаю, что NSOperationQueue натыкается на то, что он сохраняет счет до завершения всех задач. - person dstnbrkr; 24.03.2010

Разве вы не можете использовать объект [NSOperation mainQueue], чтобы вам не нужно было беспокоиться об его автоматическом освобождении? Если вам нужно добавить только одну задачу, которая кажется мне наиболее целесообразной.

http://developer.apple.com/mac/library/documentation/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html#//apple_ref/doc/uid/TP40004592-RH2-SW21

person Steven Behnke    schedule 23.03.2010
comment
Если они не хотят, чтобы эта задача выполнялась параллельно основному потоку, обрабатывающему события графического интерфейса. mainQueue работает последовательно. - person Brandon Bodnar; 23.03.2010

Нет никакой гарантии, что безопасно выпускать NSOperationQueue, пока он еще работает. Я подозреваю, возможно, это безопасно, и эта гарантия, вероятно, когда-нибудь будет добавлена, но сейчас ее нет. Однако эквивалентный Grand Central Dispatch API действительно гарантирует, что вы можете безопасно освободить свои очереди, когда закончите их использовать, и он будет хранить их до тех пор, пока они ему нужны. Так что, если вы работаете на платформе с GCD, вы можете использовать это, чтобы быть уверенным, что она не взорвется за это время.

В качестве альтернативы вы можете создать класс-оболочку, который проверяет, завершена ли очередь, и освобождает как очередь, так и себя, когда очередь завершена.

person Chuck    schedule 23.03.2010