我有一种方法,可以将其添加到已创建的GCD队列中(因此它是一个串行队列),然后异步运行它。我从该代码块中调度到主队列,当该代码块调度到主队列完成时,将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
做什么样的魔术?我需要更好地理解这一点。 最佳答案
主线程的NSRunLoop作业的一部分是运行在主线程上排队的所有块。通过在while循环中旋转,可以防止runloop进行,因此,除非您明确使循环自己运行,否则永远不会运行排队的块。
Runloop是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];
}];
关于objective-c - 等待条件继续,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13824394/