NSTimer不在子线程中触发

时间:2012-07-20 06:18:46

标签: objective-c ios nstimer nsthread

我试图让NSTimer在子线程中触发。我的代码基本上是这样的:

-(void) handleTimer:(NSTimer *)theTimer {  
    NSLog(@"timer fired");  
}

-(void) startMyThread {  
    // If I put timer in here, right before I start my new thread, it fires.  
    // [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:NO];  
    [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];  
}

// This method is called from inside the new thread  
-(void) playNote:(Note *)theNote withTemplate:(NSString *)theTemplate X:(int)x andY:(int)y {
    NSLog(@"before timer");  
    // The timer doesn't fire in here. (But the print statements do.)  
    [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:NO];
    NSLog(@"after timer");  
}

我真的想(读:需要?)在子线程中触发计时器,因为它将用于阻止音符播放(并且所有音符播放都需要在子线程中发生)。

我必须错过NSTimer在子线程中的运行方式......
过早谢谢你的帮助!

4 个答案:

答案 0 :(得分:5)

除非在运行循环中安排计时器,否则计时器不会触发。你也想避免不假思索地开辟线索。

除非你的run方法启动一个运行循环,否则你的计时器不会触发。

更好的解决方案,顺便说一句,可能是使用GCD的dispatch_after()。它比线程重量轻,但它取决于你需要做什么。但是,一般而言,队列是一种向应用程序添加并发性的更有效方法。


从评论中抓取代码以获得正确的格式(良好的查找):

double delayInSeconds = .2;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    NSLog(@"dispatch popped");
});

另外一个说明;您可以考虑使用其中一个全局并发队列。当主事件循环可能阻塞时,它们不会阻塞。当然,如果您要更新UI,则无论如何都必须返回到MEL。

答案 1 :(得分:3)

您应该将NSTimer添加到currentRunLoop。您的playNote方法应如下所示:

-(void) playNote:(Note *)theNote withTemplate:(NSString *)theTemplate X:(int)x andY:(int)y
{
    NSLog(@"before timer");  
    // The timer doesn't fire in here. (But the print statements do.)  
    NSTimer myTimer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(handleTimer:) userInfo:nil repeats:NO];
    [[NSRunLoop currentRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"after timer");  
}

应该这样做:)

答案 2 :(得分:0)

将计时器添加到当前runlooprun

-(void) handleTimer:(NSTimer *)theTimer {  
    NSLog(@"timer fired");  
}

-(void) startMyThread {  
    // If I put timer in here, right before I start my new thread, it fires.  
    // [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:NO];  
    [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];  
}

// This method is called from inside the new thread  
-(void) playNote:(Note *)theNote withTemplate:(NSString *)theTemplate X:(int)x andY:(int)y {
    NSLog(@"before timer");  
    // The timer doesn't fire in here. (But the print statements do.)  
    NSTimer *Timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(handleTimer:) userInfo:nil repeats:NO];
    NSLog(@"after timer");  
    [[NSRunLoop currentRunLoop] addTimer:Timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
}

答案 3 :(得分:0)

addTimer:内尝试[NSRunLoop mainRunLoop],而不是current!{/ p>