我有一个方法,我添加到我创建的GCD队列(所以它是一个串行队列),然后运行它async。从该代码块中我调度到主队列,当调度到主队列的代码块完成时,我将BOOL标志设置为YES,这样我在代码中进一步向下可以检查这个条件是否为YES然后我可以继续下一个方法。以下是代码:
dispatch_queue_t queue = dispatch_queue_create("ProcessSerialQueue", 0);
dispatch_async(queue, ^{
Singleton *s = [Singleton sharedInstance];
dispatch_sync(dispatch_get_main_queue(), ^{
[s processWithCompletionBlock:^{
// Process is complete
processComplete = YES;
}];
});
});
while (!processComplete) {
NSLog(@"Waiting");
}
NSLog(@"Ready for next step");
但是这不起作用,因为dispatch_sync永远不能在主队列上运行代码。这是因为我在主队列上运行了一个while循环(渲染它很忙)?
但是,如果我将while循环的实现更改为:
while (!processComplete) {
NSLog(@"Waiting")
NSDate *date = [NSDate distantFuture];
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:date];
}
它没有故障。对于这种情况,这是否可接受?我可以用其他任何首选方式吗? NSRunLoop
做了什么样的神奇事情?我需要更好地理解这一点。
答案 0 :(得分:2)
主线程的NSRunLoop作业的一部分是运行在主线程上排队的任何块。通过在while循环中旋转,您将阻止runloop进行,因此除非您明确地自行运行循环,否则排队的块永远不会运行。
Runloops是Cocoa的一个有趣的部分,documentation非常好,所以我推荐阅读它。
通常,我会避免在您执行时手动调用runloop。如果你有多个手动调用在彼此之上运行,你会浪费内存并使事情变得非常复杂。
但是,有一种更好的方法可以做到这一点。将方法拆分为-process和-didProcess方法。使用-process方法启动异步操作,完成后,从完成块调用-didProcess。如果需要将变量从一个方法传递到另一个方法,可以将它们作为参数传递给-didProcess方法。
例如:
dispatch_queue_t queue = dispatch_queue_create("ProcessSerialQueue", 0);
dispatch_async(queue, ^{
Singleton *s = [Singleton sharedInstance];
dispatch_sync(dispatch_get_main_queue(), ^{
[s processWithCompletionBlock:^{
[self didProcess];
}];
});
});
你也可以考虑让你的单身人士拥有调度队列并让它负责处理dispatch_async的东西,因为如果你总是异步地使用它,它将节省所有那些讨厌的嵌入式块。
例如:
[[Singleton sharedInstance] processAyncWithCompletionBlock:^{
NSLog(@"Ready for next step...");
[self didProcess];
}];
答案 1 :(得分:1)
做类似你发布的内容很可能会冻结用户界面。而不是冻结所有内容,在完成块中调用“下一步”代码。
示例:强>
dispatch_queue_t queue = dispatch_queue_create("ProcessSerialQueue", 0);
dispatch_queue_t main = dispatch_get_main_queue();
dispatch_async(queue, ^{
Singleton *s = [Singleton sharedInstance];
dispatch_async(dispatch_get_main_queue(), ^{
[s processWithCompletionBlock:^{
// Next step code
}];
});
});
答案 2 :(得分:-2)
不要创建类似于在块内等待值的循环,块中的变量是只读的,而是从块内部调用完成代码。
dispatch_async(queue, ^{
Singleton *s = [Singelton sharedInstance];
[s processWithCompletionBlock:^{
//process is complete
dispatch_sync(dispatch_get_main_queue(), ^{
//do something on main queue....
NSLog(@"Ready for next step");
});
}];
});
NSLog(@"waiting");