Сделайте NSOperation синхронным - PullRequest
3 голосов
/ 07 февраля 2012

Я работаю над приложением, которое позволяет пользователю создавать файлы и папки в облаке с iPad. Когда файл удаляется, приложение автоматически создает папку «Корзина» в облаке и помещает этот файл в нее. Я создал NSOperationQueue для всех операций, т. Е. У меня есть отдельная очередь для создания папки и отдельная очередь для загрузки файла. Проблема, с которой я сталкиваюсь, заключается в том, что операция по загрузке файла выполняется до завершения операции по созданию папки, и поэтому файл не загружается успешно.

Может ли кто-нибудь помочь мне сделать операцию создания папки синхронной?

Я попробовал следующий код

[create_folder_queue addOperations:[NSArray arrayWithObject:folderOperation] waitUntilFinished:YES];

но операция не выполняется.

Заранее спасибо.

Ответы [ 6 ]

12 голосов
/ 07 февраля 2012

Если вы хотите синхронную очередь, запустите метод -setMaxConcurrentOperationCount: в своей очереди операций, чтобы установить его на 1.

После установки этого свойства в очереди будет одновременно выполняться не более одной операции, что является более или менее определением синхронной очереди, в которой одна задача следует только после завершения другой.

4 голосов
/ 09 мая 2012

Насколько мне известно, один NSOperation объект может зависеть от другого, и его выполнение не обязательно в одной и той же очереди операций.Поэтому вы можете сделать следующее:

// create queues
NSOperationQueue *folder_creation_queue = [[NSOperationQueue alloc] init];
NSOperationQueue *file_uploading_queue  = [[NSOperationQueue alloc] init];
// create operations
NSInvocationOperation *folder_creation_operation = [[NSInvocationOperation alloc] 
                                                     initWithTarget:aFolderTarget 
                                                     selector:@selector(folderCreation) 
                                                     object:aFolderObject];
NSInvocationOperation *file_uploading_operation = [[NSInvocationOperation alloc] 
                                                     initWithTarget:aFileTarget 
                                                     selector:@selector(fileUpload) 
                                                     object:aFileObject];
// Set dependency for the folder_uploading_operation. 
// It prevents this operation begin executing before 
// folder_creation_operation finished.
[file_uploading_operation addDependency:folder_creation_operation];
// Execute these operations
[folder_creation_queue addOperation:folder_creation_operation];
[file_uploading_queue addOperation:file_uploading_operation];

Обратите внимание, что в этом примере управление памятью отсутствует.

1 голос
/ 24 января 2019

Вы, вероятно, не должны использовать отдельные очереди операций.Поскольку это все операции с облачными файлами, у вас должна быть одна очередь операций с облачными файлами, выполняющая все операции с облачными файлами.

Если операции не зависят от других операций, вы просто добавляете их в эту очередь, и они выполняютсяв любом порядке и столько, сколько система считает полезной.Конечно, вы можете установить maxConcurrentOperationCount, чтобы установить свой собственный предел, если вы считаете, что это хорошая идея, но вам это не нужно, и в этом случае система решит за вас.

ВОперации case зависят друг от друга, вы используете систему зависимости операций.Для этого сначала создайте операции, а затем используйте addDependency, чтобы сообщить системе, какая операция зависит от какой другой операции.Если вы теперь добавите все эти операции в очередь, система обязательно выполнит их в правильном порядке, так что операция будет выполняться только после того, как все операции, от которых она зависит, будут завершены (и они могут снова зависеть от других операций и т. Д.).на).Просто убедитесь, что не созданы циклические зависимости (OpA зависит от OpB, который зависит от OpC, который зависит от OpA), так как тогда ни один из них никогда не будет работать.

Но, чтобы ответить на вопрос в целом, в случае, если другие пользователиспросите, как вы можете смоделировать dispatch_sync с NSOperationQueue:

NSOperationQueue * queue = ...;
NSOperation * someOperation = [NSBlockOperation
    blockOperationWithBlock:^{
        // ... do whatever you want to do ...
    }
];
[queue addOperation:someOperation];
[someOperation waitUntilFinished];

Обратите внимание, однако, что это гораздо менее эффективно, чем вызов dispatch_sync в очереди последовательной отправки, поскольку приведенный выше код всегда вызывает переключение двух потоковв то время как вызов dispatch_sync в очереди последовательной отправки повторно использует вызывающий поток для запуска блока, и, таким образом, переключение потока вообще не будет происходить, и процессу не потребуется второй поток для этого. Подробнее о том, как это работает, см. Здесь .

1 голос
/ 07 февраля 2012

Вместе с setMaxConcurrentOperationCount в вашем подклассе NSOperation:

- (void)main
{    
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    [pool release];
}

- (BOOL)isConcurrent {
    return FALSE;
}

Теперь он находится в режиме полностью последовательной последовательности.

1 голос
/ 07 февраля 2012

Это должно решить вашу проблему:

[create_folder_queue addOperation:folderOperation];
[create_folder_queue waitUntilAllOperationsAreFinished];

// ... now start file upload ...
0 голосов
/ 07 февраля 2012

Почему у вас две очереди? Если у вас может быть только один, то ваша проблема решается с помощью зависимостей (см. Документацию ).

...