2

我正在尝试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

4 回答 4

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。

于 2012-07-20T06:23:17.600 回答
3

您应该添加NSTimercurrentRunLoop. 您的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");  
}

应该这样做:)

于 2012-07-20T06:40:01.913 回答
1

将计时器添加到当前runloop, 和run.

-(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];
}
于 2012-07-20T06:23:21.947 回答
0

尝试addTimer:内之[NSRunLoop mainRunLoop],而不是内之current

于 2016-07-28T11:09:02.833 回答