使NSOperation同步

时间:2012-02-07 08:01:26

标签: iphone ios nsoperation nsoperationqueue

我正在开发一款允许用户通过iPad在云端创建文件和文件夹的应用。 删除文件后,应用程序会自动在云上创建“回收站”文件夹并将该文件放入其中。我为所有操作创建了NSOperationQueue,即我有单独的文件夹创建队列和单独的文件上载队列。我面临的问题是,文件上传操作在文件夹创建操作完成之前执行,因此文件无法成功上传。

有人可以帮我把文件夹创建操作同步吗?

我尝试过以下代码

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

但它不执行操作。

提前致谢。

6 个答案:

答案 0 :(得分:12)

如果需要同步队列,请在操作队列上运行-setMaxConcurrentOperationCount:方法将其设置为1

设置此属性后,队列中一次最多只能运行一个操作,这或多或少是同步队列的定义,其中一个任务仅在另一个任务完成后才会执行。

答案 1 :(得分:4)

据我所知,一个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];

注意本例中没有内存管理。

答案 2 :(得分:1)

这可以解决您的问题:

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

// ... now start file upload ...

答案 3 :(得分:1)

setMaxConcurrentOperationCount一起,在NSOperation子类中 :

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

    [pool release];
}

- (BOOL)isConcurrent {
    return FALSE;
}

现在它处于完全串行序列模式。

答案 4 :(得分:1)

您可能不应该使用单独的操作队列。由于这些都是云文件操作,因此您应该有一个云文件操作队列执行所有云文件操作。

如果这些操作不依赖于其他操作,则只需将它们添加到此队列中,即可按照系统认为有用的任何顺序执行这些操作,并且可以同时执行这些操作。当然,如果您认为这是个好主意,则可以设置maxConcurrentOperationCount来对此设置自己的限制,但是不必这样做,在这种情况下,系统将为您做出决定。

如果操作确实相互依赖,请使用操作依赖系统。因此,您首先创建操作,然后使用addDependency告诉系统哪个操作取决于哪个其他操作。如果现在将所有这些操作添加到队列中,系统将确保以正确的顺序运行它们,以便某个操作仅在其所依赖的所有操作完成后才能运行(并且这些操作可能再次取决于其他操作,因此上)。只要确保不创建循环依赖项(OpA依赖于OpB,OpC依赖于OpC,OpA依赖于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则会将调用线程重用到运行该块,因此根本不会发生线程切换,该过程也不需要第二个线程来执行。 See here,详细了解其工作原理。

答案 5 :(得分:0)

为什么你有两个队列?如果您只有一个,那么您的问题就会被依赖项解决(请参阅documentation)。