我目前正在开发一个运行自己的事件循环的应用程序。如果我在没有从另一个调度中排队时使用调度异步,则其块正确运行。
示例:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"This should appear!");
});
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:NSDefaultRunLoopMode
dequeue:YES];
[NSApp sendEvent:event];
}
如果我运行它,将按预期调用日志。
但是,让我说我把这个调度包裹起来,就像这样:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"This should appear!");
});
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:NSDefaultRunLoopMode
dequeue:YES];
[NSApp sendEvent:event];
}
});
如果我运行此代码,则不会执行日志。我可以想象,因为extEventMatchingMask:在一个排队的块中被调用,它将无法处理将来调度的块。但奇怪的是,如果我使用performSelector:它甚至会在排队的块中执行。
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"This should appear!");
});
[self performSelector:@selector(logAppear) withObject:nil afterDelay:2];
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:NSDefaultRunLoopMode
dequeue:YES];
[NSApp sendEvent:event];
}
});
-(void) logAppear {
NSLog(@"This should appear!");
}
如果我运行此示例,将按预期调用方法logAppear。
所以,简而言之,我想问为什么第二种情况不起作用,以及如何(如果可能的话)我可以在一个能够运行调度块的入队块中运行事件循环。
答案 0 :(得分:0)
经过一些实验后,我意识到我需要做的是确保在任何排队的块之外执行该事件循环。我们可以通过将循环放在方法中并确保它由performSelector调用来完成此操作。
示例:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"This should appear!");
});
[self performSelector:@selector(logAppear) withObject:nil afterDelay:2];
[self performSelector:@selector(mainLoop) withObject:nil afterDelay:0];
});
-(void) mainLoop {
for (;;)
{
NSEvent* event = [NSApp nextEventMatchingMask:NSAnyEventMask
untilDate:[NSDate distantPast]
inMode:NSDefaultRunLoopMode
dequeue:YES];
[NSApp sendEvent:event];
}
}
-(void) logAppear {
NSLog(@"This should appear!");
}
通过运行此示例,我们现在可以按预期获得两个日志