簡體   English   中英

全局隊列中的計時器未在iOS中調用

[英]Timer inside global queue is not calling in iOS

-(void)viewDidLoad{
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        [NSTimer scheduledTimerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        }
    );
}

-(void)action_Timer{
    LOG("Timer called");
}

沒有調用action_Timer 我不知道為什么。 你有什么主意嗎?

您正在從GCD工作線程調用+[NSTimer scheduledTimerWithTimeInterval:...] GCD工作線程不運行運行循環。 這就是為什么你的第一次嘗試不起作用的原因。

當您嘗試[[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode] ,您正在從GCD工作線程向主運行循環發送消息。 NSRunLoop存在的問題不是線程安全的。 (這在NSRunLoop類參考中有記錄 。)

相反,您需要調度回主隊列,以便在將addTimer:...消息發送到主運行循環時,它在主線程上完成。

-(void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSTimer *timer = [NSTimer timerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        dispatch_async(dispatch_get_main_queue(), ^{
            [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        });        
    });
}

實際上,如果您要在主運行循環中安排計時器,則沒有理由在后台隊列上創建計時器。 您可以調度回主隊列來創建和安排它:

-(void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSLog(@"on background queue");
        dispatch_async(dispatch_get_main_queue(), ^{
            NSLog(@"on main queue");
            [NSTimer scheduledTimerWithTimeInterval:0.10 
                                         target:self 
                                       selector:@selector(action_Timer) 
                                       userInfo:nil 
                                        repeats:YES];
        });        
    });
}

請注意,我的兩個解決方案都將計時器添加到主運行循環中,因此計時器的操作將在主線程上運行。 如果您希望計時器的操作在后台隊列上運行,您應該從操作中調度它:

-(void)action_Timer {
    // This is called on the main queue, so dispatch to a background queue.
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        LOG("Timer called");
    });
}

您必須將計時器添加到主運行循環以啟動計時器,但首先,您應該在私有ivar或屬性中保持對計時器的引用:

-(void)viewDidLoad{
        // on the main queue
        self.mytimer = [NSTimer scheduledTimerWithTimeInterval:0.10 
                                                        target:self 
                                                      selector:@selector(action_Timer) 
                                                      userInfo:nil 
                                                        repeats:YES];
        [[NSRunLoop mainRunLoop] addTimer:myTimer forMode:NSDefaultRunLoopMode];
}

-(void)action_Timer{
    dispatch_async( dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
        LOG("Timer called");
    });
}

我發現在被調用的方法中更容易脫離主隊列。 在某些點,也許在viewDidUnloddealloc ,你將調用[self.myTimer invalidate]; self.myTimer = nil; [self.myTimer invalidate]; self.myTimer = nil;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM