Сделайте NSOperation синхронным
Я работаю над приложением, которое позволяет пользователю создавать файлы и папки в облаке с iPad. Когда файл удаляется, приложение автоматически создает папку "Корзина" в облаке и помещает этот файл в нее. Я создал NSOperationQueue
для всех операций, т.е. у меня есть отдельная очередь для создания папки и отдельная очередь для загрузки файла. Проблема, с которой я сталкиваюсь, заключается в том, что операция загрузки файла выполняется до того, как операция создания папки завершена, и поэтому файл не загружается успешно.
Кто-нибудь может мне помочь сделать операцию создания папки синхронной?
Я пробовал следующий код
[create_folder_queue addOperations:[NSArray arrayWithObject:folderOperation] waitUntilFinished:YES];
но он не выполняет операцию.
Заранее спасибо.
5 ответов
Если вы хотите синхронную очередь, запустите -setMaxConcurrentOperationCount:
метод в вашей очереди операций, чтобы установить его 1
,
После установки этого свойства в очереди будет одновременно выполняться не более одной операции, что является более или менее определением синхронной очереди, в которой одна задача следует только после завершения другой.
Насколько я знаю один 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];
Обратите внимание, что в этом примере управление памятью отсутствует.
Вы, вероятно, не должны использовать отдельные очереди операций. Поскольку это все операции с облачными файлами, у вас должна быть одна очередь операций с облачными файлами, выполняющая все операции с облачными файлами.
Если операции не зависят от других операций, вы просто добавляете их в эту очередь, и они выполняются в любом порядке и столько же, сколько система считает полезными. Конечно, вы можете установить maxConcurrentOperationCount
установить собственное ограничение на это, если вы считаете, что это хорошая идея, но вам это не нужно, и в этом случае система решит за вас.
В случае, если операции зависят друг от друга, вы используете систему зависимости операций. Для этого вы сначала создаете операции, а затем используете 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
в очереди последовательной отправки будет повторно использоваться вызывающий поток для запуска блока, и, таким образом, переключение потока вообще не будет происходить, и процессу не потребуется второй поток для этого. Смотрите здесь для деталей о том, как это работает.
Вместе с setMaxConcurrentOperationCount
, в вашем NSOperation
подкласс:
- (void)main
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[pool release];
}
- (BOOL)isConcurrent {
return FALSE;
}
Теперь это в полностью последовательном режиме последовательности.
Это должно решить вашу проблему:
[create_folder_queue addOperation:folderOperation];
[create_folder_queue waitUntilAllOperationsAreFinished];
// ... now start file upload ...
Почему у вас две очереди? Если у вас может быть только один, то ваша проблема решается с помощью зависимостей (см. Документацию).