Objective c 使用dispatch\u sync强制执行顺序
My library向以下用户公开了2个API:Objective c 使用dispatch\u sync强制执行顺序,objective-c,multithreading,grand-central-dispatch,dispatch-async,Objective C,Multithreading,Grand Central Dispatch,Dispatch Async,My library向以下用户公开了2个API: -(void) createFile{ dispatch_sync(queueSerial, ^{ //B1 [fileObj createFileInfo:file completion:^(NSError *error){ //execute completion block C1 }]; }); } -(void) readFile:(NSData*)timeStamp{
-(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
});
}]
});
}
readFile
和createFile
都是异步方法
我通常建议使用我的库的人在readFile
之前调用createFile
。但是,无法保证呼叫者最终将如何实现这一点。它通常以以下方式被调用(而我对此没有控制权)
我要做的是确保在执行完成块C1
后调用readFile
。我也不想用createFile
阻塞主线程(但是这个期望可以放宽)。因此,我想要实现的最终结果是:
createFile
并在调用之后立即调用readFile
createFile
完全执行,完成块C1
被激发,之后
就是说,readFile
被分派去做它的事情我怎样才能做到这一点呢?感觉就像是在尝试采用一个现有的基于完成处理程序的API,并将其转换为一个串行队列模式。但串行队列只有在调度的块本身是同步的情况下才有意义。(不要将此与
分派\u 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
工作
说到这里,我想知道你的setFile
和getFile
方法比FileObject
类自己的方法增加了什么附加值
但关键是,在处理异步方法时,您不能轻松地将它们与简单的串行GCD队列进行协调。如果您想为自己的异步任务分配调度队列行为,那么通常会考虑使用操作队列(或承诺/期货或类似的操作)。.我明白你想说什么,但问题是我只能控制
setFile
getFile
方法,而不能控制它们是如何被调用的。所以,我需要绕过这个限制。我能做的最好的事情就是在setFileInfo
完成后强制发送getFileInfo
,然后你应该编辑你的问题,分享他们是如何被调用的(并解释为什么不能更改他们)。但这里的基本事实是,您不能仅仅采用异步方法并将它们添加到队列中,然后期望队列能够处理它们。从理论上讲,你可以使它们同步,但这确实是一个可怕的想法(有很多原因)。如果您愿意,您可以创建这些异步NSOperation
子类,但这也改变了您的API(虽然有点酷,但需要做更多的工作才能正常工作)。请编辑包含您对API有哪些约束的问题…就这些方法添加的值而言,它们是此类FileObject
中唯一向调用我的流程的客户端公开的方法。我并非完全不反对使用其他方法来实现这一点。只是setFile
方法计算量很大,需要在调用getFile
之前执行,因为它的时间敏感时间戳expirest这就是我的foo
/bar
示例所做的(不过,我重命名了它们,因为您不应该使用set
前缀命名非访问器方法……如果使用set
启动非访问器方法,您将引入奇怪的警告。)但是只有当计算密集型的foo
完成时,上面才会调用bar
,但不会阻止调用线程来实现这一点。我更新了我的问题,澄清了限制。在完成块C1
中使用锁定和解锁是个好主意吗?@Rob感谢您的洞察力。我是一个完全的新手(在Obj C中)在这一点上,因此我将尝试从今以后遵循您的建议。readFile
如何传回它读取的数据?它被定义为返回void
,因此它必须使用完成处理程序或委托模式?@RobreadFile
传递数据(如果有错误值)在完成处理程序C2中。我不确定这些部分是否相关。
[self foo:^{
[self bar:^{
// do whatever you want when its all done
}];
}];