Reputation: 39
I am working on an app that allows an user to create files and folders on the cloud from iPad.
When a file is deleted, the app automatically creates a 'Recycle Bin' folder on the cloud and puts that file in it. I have created NSOperationQueue
for all the operations i.e. I have separate queue for Folder Creation and a separate queue for File Upload. The problem that I am facing is that, the operation for file upload gets executed before the operation for folder creation is completed and so file doesn't gets uploaded successfully.
Can anyone help me to make the folder creation operation synchronous?
I have tried the following code
[create_folder_queue addOperations:[NSArray arrayWithObject:folderOperation] waitUntilFinished:YES];
but it doesn't execute the operation.
Thanks in advance.
Upvotes: 4
Views: 8479
Reputation: 132869
You probably shouldn't use separate operation queues. As these are all cloud file operations, you should have one cloud file operation queues performing all cloud file operations.
If the operations don't depend on other operations, you just add them to this queue and they are performed in any order and as many of them at the same time as the system considers useful. Of course, you can set maxConcurrentOperationCount
to place your own limit on this if you think that is a good idea, but you don't have to, in which case the system will decide for you.
In case operations do depend on each other, you use the operation dependency system. Therefor you first create the operations and then use addDependency
to tell the system which operation depends on which other operation. If you now add all these operations to the queue, the system will make sure to run them in the correct order, so that an operation will only run after all operations it depends on have finished (and these may again depend on other operations and so on). Just make sure to not created cyclic dependencies (OpA depends on OpB which depends on OpC which depends on OpA) as then none of them will ever run.
But to the answer the question in general, in case other users ask how you can simulate a dispatch_sync
with NSOperationQueue
:
NSOperationQueue * queue = ...;
NSOperation * someOperation = [NSBlockOperation
blockOperationWithBlock:^{
// ... do whatever you want to do ...
}
];
[queue addOperation:someOperation];
[someOperation waitUntilFinished];
Note however, that this far less performant than calling dispatch_sync
on a serial dispatch queue since the code above always causes two thread switches whereas calling dispatch_sync
on a serial dispatch queue will reuse the calling thread to run the block and thus no thread switch at all will take place, nor will the process require a second thread to do so. See here for details on how this works.
Upvotes: 2
Reputation: 2297
Along with setMaxConcurrentOperationCount
, in your NSOperation
subclass
:
- (void)main
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[pool release];
}
- (BOOL)isConcurrent {
return FALSE;
}
Now it's in a completely serial sequence mode.
Upvotes: 1
Reputation: 376
As far as I know one NSOperation
object can depend on other and it is not mandatory for them to be executed in the same operation queue. So you can do next:
// 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];
Pay attention that there is no memory management in this example.
Upvotes: 4
Reputation: 35384
This should solve your issue:
[create_folder_queue addOperation:folderOperation];
[create_folder_queue waitUntilAllOperationsAreFinished];
// ... now start file upload ...
Upvotes: 1
Reputation: 96927
If you want a synchronous queue, run the -setMaxConcurrentOperationCount:
method on your operation queue to set it to 1
.
After setting this property, you will only have at most one operation running at a time in the queue, which is more or less the definition of a synchronous queue, where one task only follows after another is complete.
Upvotes: 11
Reputation: 1673
Why do you have two queues? If you can have only one, then your problem is solved with dependencies (see the documentation).
Upvotes: 0