我经常搜索其他人是如何解决这个问题的,但不幸的是,我没有找到这个具体问题的答案。我非常感谢你的帮助。
以下是摘要: 我的类中有两个方法,method1和method2。我必须在method1中调用异步函数。然后代码继续执行并到达method2。但是在method2中,有些情况下我需要在method1中使用该异步调用的结果,所以我需要确保在继续使用方法2的其余部分之前,方法1中的异步调用已经完成。
我知道一种方法是使用信号量,另一种方法是使用完成块。但我想以最通用的方式执行此操作,因为将有其他方法,类似于method2,它将再次需要在继续执行之前等待method1中的异步调用完成。同样出于同样的原因,我不能简单地在method2本身中调用async函数,并将其余的method2放在其完成块中。
这里对我想要做的事情有一个粗略的了解。如果有人将完成块添加到这个伪代码中,我会很感激,所以我可以清楚地看到事情是如何工作的。 BTW,method1和method2(以及此类中的所有其他方法)在同一个线程上(但不是主线程)。
@implementation someClass
-(void)method1 {
for (each item in the ivar array) {
if (condition C is met on that item) {
some_independent_async_call(item, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(int result, int *someArray) {
if (result > 0) {
// The async call worked correctly, we will need someArray
}
else {
// We didn't get someArray that we wanted.
}
});
}
}
}
-(void)method2 {
// Select one item in the ivar array based on some criteria.
if (condition C is met on that item) {
// Wait for some_independent_async_call() in method1 to complete.
// Then use someArray in the rest of the code.
}
else {
// Simply continue the rest of the code.
}
}
@end
更新:我知道一旦异步调用完成,我就可以发出信号量信号,我可以在method2中等待相同的信号量,但是我想使用完成块,因为我认为这样会更通用,尤其是如果有其他的话与此类中的method2类似的方法。有人可以为这段代码添加完成块,因为我在使这项工作有问题吗?
答案 0 :(得分:1)
基于您的代码,您可以控制异步调度。
而不是some_independent_async_call
使用dispatch_sync
,它将阻止当前线程的执行,直到给定的块完成
using dispatch_sync in Grand Central Dispatch
但是,如果您无法控制异步调用,并且实际上正在调用某个对象的方法,那么该方法将调用dispatch_async
;你没有选择使用完成块,回调模式或信号量,如你所说
答案 1 :(得分:1)
所以,如果我已正确理解你的问题,你就会有一个" Items"和一个异步任务。该任务采用参数item
并计算一些"结果" (一系列的Ints)。
现在,对于每个"项目"将评估一个布尔值,该值确定是否应该使用此项作为参数启动任务。
完成每项任务(你的some_independent_async_call
)后,你想调用一个延续(可能使用相应完成任务的结果)。
当然可以使用调度组,完成处理程序,NSOperations等来实现它。但是这很快就会变得非常精细且容易出错,特别是如果你想处理错误并且可能在需要时实现取消任务的方法。但是,因为这对于"期货"变得非常简单。我会提出这个解决方案。
请注意"期货"不包含在标准Swift库中。但是,有一些第三方库可用。在这里,我将使用"Scala-like" futures。注意,这可以用" Promises"来实现。也以类似的方式。另请参阅wiki Futures and Promises。
利用期货,任务有以下特征:
typealias TaskType = (Item) -> Future<SomeResult>
未来是一个&#34;占位符&#34;对于稍后将由底层异步任务计算的值。任务也可能失败并返回错误而不是值。也就是说,未来将最终完成结果或错误。
让任务成为:
func task(item: Item) -> Future<SomeResult> {
let promise = Promise<SomeResult>()
fetchSomeResult(item.url) { (result, error) in
if let result = result {
promise.fulfill(result)
} else {
promise.reject(error!)
}
}
return promise.future!
}
过滤数组以获得实际的&#34;项目&#34;似乎更容易。开始一项任务:
let activeItems = items.filter { $0.foo == something }
获得一系列期货:
let futures = activeItems.map { task($0) }
上述语句将启动异步任务,每个异步任务都有相应的项目,并返回类型为[Future<SomeResult>]
的未来数组。目前,期货尚未完成。当底层任务完成时,这将最终发生在每个未来。
现在,为任务成功时调用的每个future添加一个continuation,并添加一个错误处理程序,当一个错误处理程序出现时调用它:
futures.forEach { future in
future.map { result in
// This will be entered for each task, once it
// finished successfully.
// Handle result (should be your array of ints)
// This is where you implement the "method2" part
// but for each item separately.
// Note: if you need the "item" as well, use a
// task which returns a tuple:
// task(item: Item) -> Future<(Item, SomeResult)>
}.onFailure { error in
// handle error. This is an error returned from the task.
}
}