NSTimer作为超时机制

时间:2010-06-02 21:46:45

标签: iphone cocoa multithreading nstimer

我很确定这很简单,我只是遗漏了一些明显的东西。我有一个应用程序需要从Web服务下载数据以便在UITableView中显示,如果操作需要超过X秒才能完成,我想显示UIAlertView。所以这就是我所拥有的(简化为简洁):

MyViewController.h

@interface MyViewController : UIViewController
        <UITableViewDelegate, UITableViewDataSource> {
    NSTimer *timer;
}

@property (nonatomic, retain) NSTimer *timer;

MyViewController.m

@implementation MyViewController

@synthesize timer;

- (void)viewDidLoad {
    timer = [NSTimer scheduledTimerWithTimeInterval:20
          target:self
        selector:@selector(initializationTimedOut:)
        userInfo:nil
         repeats:NO];

    [self doSomethingThatTakesALongTime];
    [timer invalidate];
}

- (void)doSomethingThatTakesALongTime {
    sleep(30); // for testing only
    // web service calls etc. go here
}

- (void)initializationTimedOut:(NSTimer *)theTimer {
    // show the alert view
}

我的问题是,我期待[self doSomethingThatTakesALongTime]调用阻塞,而计时器一直在计数,我想如果它在计时器完成倒计时之前完成,它将返回线程的控制权到viewDidLoad [timer invalidate]将继续取消计时器。显然我对定时器/线程如何工作的理解是有缺陷的,因为编写代码的方式,定时器永远不会消失。但是,如果我删除[timer invalidate],则会删除。

3 个答案:

答案 0 :(得分:3)

我认为在同一个线程上调度计时器和执行阻塞调用存在问题。在阻塞调用完成之前,运行循环无法触发计时器。

我建议你分离一个线程来执行长时间的操作。完成长操作后,回调主线程以使计时器无效。

注意:在计划的同一个线程上使计时器失效非常重要。

- (void)viewDidLoad {
    timer = [NSTimer scheduledTimerWithTimeInterval:20
          target:self
        selector:@selector(initializationTimedOut:)
        userInfo:nil
         repeats:NO];

    [NSThread detachNewThreadSelector:@selector(doSomethingThatTakesALongTime:) toTarget:self withObject:nil];
}

- (void)doSomethingThatTakesALongTime:(id)arg {
    sleep(30); // for testing only
    // web service calls etc. go here
    [self performSelectorOnMainThread:@selector(invalidate) withObject:nil waitUntilDone:NO];
}

- (void)invalidate {
    [timer invalidate];
}

- (void)initializationTimedOut:(NSTimer *)theTimer {
    // show the alert view
}

答案 1 :(得分:0)

您是否尝试过使用[NSThread sleepforTimeInterval:30];

答案 2 :(得分:0)

sleep()出现在主线程上,相关的运行循环永远不会有机会调用计时器的选择器。

如果您要在-doSomething中进行实际工作但不阻止该主题,例如对Web服务的非阻塞调用,它将按预期工作。但是,阻塞调用必须在不同的线程中完成,因此主运行循环不会被阻塞。