【问题标题】:Make NSOperation synchronous使 NSOperation 同步
【发布时间】:2012-02-07 08:01:26
【问题描述】:

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

谁能帮我使文件夹创建操作同步?

我试过下面的代码

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

但它不执行操作。

提前致谢。

【问题讨论】:

  • 向我们展示更多代码(您从哪里调用 addOperations,folderOperation 是什么类型)

标签: iphone ios nsoperation nsoperationqueue


【解决方案1】:

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

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

【讨论】:

  • 嗨,Alex,感谢您的回复,但我有两个单独的队列,一个用于创建文件夹,另一个用于文件上传,它们同时执行..在 1 上设置并发操作不会有太大区别..
  • 然后您可能想阅读 Apple 的 Managing Concurrency 文档,尤其是有关依赖项的部分:developer.apple.com/cocoa/managingconcurrency.html
  • 同步是指线程按顺序运行(一个接一个)还是在主线程上运行?
  • 这是串行队列的定义,不是同步队列。调用线程可能在同步操作执行之前完成。
【解决方案2】:

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

注意这个例子中没有内存管理。

【讨论】:

  • 您能否将此代码应用于常规方法“例如从服务器提取数据的 get 操作”。我需要拉取数据,为了保持关系健康,拉取操作应该是连续的。
【解决方案3】:

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

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

如果操作确实相互依赖,则使用操作依赖系统。因此,您首先创建操作,然后使用addDependency 告诉系统哪个操作依赖于其他操作。如果您现在将所有这些操作添加到队列中,系统将确保以正确的顺序运行它们,以便一个操作仅在它所依赖的所有操作都完成后运行(并且这些可能再次依赖于其他操作,因此在)。只要确保不创建循环依赖项(OpA 依赖于 OpB,OpB 依赖于 OpC,OpC 依赖于 OpA),那么它们都不会运行。

但要回答一般问题,如果其他用户问您如何用NSOperationQueue 模拟dispatch_sync

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

但是请注意,这比在串行调度队列上调用 dispatch_sync 的性能要低得多,因为上面的代码总是会导致两个线程切换,而在串行调度队列上调用 dispatch_sync 将重用调用线程来运行块并因此根本不会发生线程切换,该过程也不需要第二个线程来这样做。 See here 了解其工作原理的详细信息。

【讨论】:

    【解决方案4】:

    这应该可以解决您的问题:

    [create_folder_queue addOperation:folderOperation];
    [create_folder_queue waitUntilAllOperationsAreFinished];
    
    // ... now start file upload ...
    

    【讨论】:

    • 感谢您的帮助。我试过这个,但这样做,操作不会被执行。我不知道我错在哪里。
    • [create_folder_queue waitUntilAllOperationsAreFinished];前后folderOperation的执行状态是什么,即isCancelledisExecutingisFinishedisReady返回什么?
    【解决方案5】:

    setMaxConcurrentOperationCount 一起,在您的NSOperation 子类中 :

    - (void)main
    {    
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    
        [pool release];
    }
    
    - (BOOL)isConcurrent {
        return FALSE;
    }
    

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

    【讨论】:

      【解决方案6】:

      为什么有两个队列?如果您只能拥有一个,那么您的问题将通过依赖关系解决(请参阅documentation)。

      【讨论】:

      • 有两个队列的原因是,我不希望用户在进行 1 个操作时处于空闲状态。例如,如果我有 1 个队列,那么如果用户上传一个大文件,那么他/她必须等到文件上传后才能执行任何其他操作(如创建文件夹、下载文件等)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 2010-12-08
      • 2012-09-19
      相关资源
      最近更新 更多