dispatch_after()的奇怪行为

时间:2014-03-04 06:29:06

标签: objective-c multithreading macos objective-c-blocks nsthread

我正在编写一个同时执行多项任务的应用程序。一项特殊任务是每隔200毫秒做一次工作。为实现这一点,我使用了两种相互调用的方法。第一种方法只调用第二种方法,第二种方法使用dispatch_after()调用第一种方法。

经过几次迭代(300-400次),在200 ms后不执行dispatch_after中的块。 执行块之前需要约5-10秒。请让我知道行为的原因(延迟)。我也试过NSThread(sleepForTimeInterval :),我也遇到了同样的问题。我卡住了。请帮帮我。

代码如下。

Screen.h

#import <Foundation/Foundation.h>

@interface Screen : NSObject

-(void) firstMethod;
-(void) secondMethod;
@end

Screen.m

#import "Screen.h"

@implementation Screen

int i=0;
dispatch_queue_t another_queue;
dispatch_time_t pop_time;

-(Screen*) init {
    self = [super init];
    if (self) {
        another_queue = dispatch_queue_create("com.test.timer.2", NULL);
    }
    return self;
}

-(void) firstMethod {
    i++;
    NSLog(@"i value : %d",i);
    [self secondMethod];
}

-(void) secondMethod {
    pop_time = dispatch_time(DISPATCH_TIME_NOW, 200 * NSEC_PER_MSEC);
    dispatch_after(pop_time, another_queue, ^(void){
        [self firstMethod];
    });
}

@end

AppDelegate.h

#import <Cocoa/Cocoa.h>
#import "Screen.h"

@interface AppDelegate : NSObject <NSApplicationDelegate>

@property (assign) IBOutlet NSWindow *window;

@end

AppDelegate.m

#import "AppDelegate.h"

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    // Insert code here to initialize your application
    Screen* screen = [[Screen alloc] init];
    dispatch_queue_t first_queue = dispatch_queue_create("com.test.timer", NULL);
    dispatch_block_t blk =^(void) {
        [screen firstMethod];
    };
    dispatch_async(first_queue, blk);
}

@end

3 个答案:

答案 0 :(得分:6)

发生这种情况时,您的应用是否处于前台?如果没有,你可能只是看到App Nap开始。它所做的一件事就是在后台应用程序中限制计时器。

答案 1 :(得分:1)

一种可能的效果是“定时器合并”和“App Nap”。

相关:这个问题:Have you noticed that dispatch_after runs ~10% too slow on iOS devices?

如果这实际上是您的问题的原因,您可以使用计时器(NSTimer)或使用我们自己的实现(基于dispatch lib)来修复它,您可以在其中控制确切的行为。另请参阅:Gist上的计时器实现:RXTimer

修改

在App Nap启动时,在Mac OS X 上,似乎我们无法分别控制延迟这个巨大的“余地”。

答案 2 :(得分:-1)

我在OS X上遇到了同样的问题。我的延迟超过了指定延迟的1000%。

关闭App Nap系统解决了这个问题:

defaults write NSGlobalDomain NSAppSleepDisabled -bool YES