1

我的图书馆强制执行顺序暴露的API 2如下到:使用dispatch_sync

-(void) createFile{ 

    dispatch_sync(queueSerial, ^{ //B1 

    [fileObj createFileInfo:file completion:^(NSError *error){ 

     //execute completion block C1 
    }]; 

    }); 
} 

-(void) readFile:(NSData*)timeStamp{ 

    dispatch_async(queueSerial, ^{ //B2 

     [fileObj readFileInfo:fileName completion:^(NSError *error) { 
      dispatch_async(queueSerial2, ^{ 

       //execute completion block C2 

      }); 
     }] 

    }); 
} 

两个readFilecreateFile是异步方法。

我通常会推荐给使用我的图书馆的人在readFile之前致电createFile。但是,不能保证呼叫者将如何最终实现这一点。它通常被用以下方式调用(和我已经在这个没有控制)

[fileClass createFile]; 
[fileClass readFile:timeStamp]; 

我想要做的是,确保在执行completion block C1readFile被调用。我也不想阻止主线程createFile(但这种期望可以放松)。所以我想达到的最终结果是:

  1. 来电(我没有控制权)调用createFile和电话readFile
  2. createFile完全执行后,立即完成块C1被解雇, 之后, readFile被派遣去做它的事情。

我该如何做到这一点?

+0

@Rob感谢您的洞察力。在这一点上,我是一个刚刚起步的人(在Obj C中),所以我会尽力遵循你的建议。 – ExceptionHandler

+0

'readFile'如何传回它读取的数据?它被定义为返回'void',所以它必须使用完成处理程序或委托模式? – Rob

+0

@Rob'readFile'传递完成处理程序C2中的数据(错误值,如果有的话)。我不确定这些部分是否相关。 – ExceptionHandler

回答

1

感觉就像你试图采用现有的基于完成处理程序的API并且将它放入串行队列模式中。但是,当分派的块本身是同步的时,串行队列才有意义。 (并且不要将它与dispatch_sync混淆......我们正在讨论块内部的任务是否是异步的,而不是你如何将它分派到你的队列中。)但是你正在处理从其他方法调用的异步方法异步方法。

处理采用完成处理程序块的方法时的基本模式是完全消除串行队列(当任务已经是异步时,不需要GCD队列或非常有用),而只需在自己的方法中使用完成处理程序块,并且让最深嵌套块中的最后一个调用调用你自己的完成处理程序。

例如:

- (void)foo:(void (^)())completion { 
    [fileObj setFileInfo:file completion:^(NSError *error) { 
     // do some other stuff 
     completion(); 
    }]; 
} 

- (void)bar:(void (^)())completion { 
    [fileObj getFileInfo:fileName completion:^(NSError *error) { 
     // do some other stuff 
     completion(); 
    }]; 
} 

然后你会打电话像这样:

[self foo:^{ 
    [self bar:^{ 
     // do whatever you want when its all done 
    }]; 
}]; 

这意味着,直到setFile东西做也不会做任何的getFile东西。

话虽如此,我不知道什么增值你的setFilegetFile方法添加上面和超过FileObject类自己的方法。

但关键在于,在处理异步方法时,不能轻易地将它们与简单的串行GCD队列进行协调。如果你想为任务本身是异步的调度队列类似的行为,那么你通常会考虑使用操作队列(或承诺/期货或类似的东西)。

+0

我明白你想说什么,但事情是我只能控制'setFile'' getFile'方法和*不* *如何不幸地调用它们。所以,我需要解决这个限制。我能做的最好的办法是在'setFileInfo'完成之后强制调度'getFileInfo' – ExceptionHandler

+0

然后你应该编辑你的问题共享如何调用(并解释它们为什么不能被改变)。但是,这里的基本事实是,你不能只采用异步方法并将它们添加到队列中,并希望队列处理它。理论上,你可以让它们同步,但这是一个非常可怕的想法(因为很多原因)。如果你愿意,你可以创建这些异步的'NSOperation'子类,但是这也改变了你的API(虽然很酷,但需要更多的工作才能正确完成)。请仅编辑这个问题,即在您的API上有什么限制...... – Rob

+0

,只要这些方法添加了什么值,它们是暴露给调用我的进程中的客户端的此类“FileObject”的唯一方法。我不完全没有反对使用其他方法来实现这一点。只是''setFile'方法的计算量很大,需要在'getFile'被调用之前执行,因为它对时间敏感'timeStamp'到期 – ExceptionHandler

相关问题