iOS多線程中performSelector: 和dispatch_time的不同 – iPhone手機開發技術文章 iPhone軟體開發教學課程

iOS中timer相關的延時調用,常見的有NSObject中的performSelector:withObject:afterDelay:這個方法在調用的時候會設置當前runloop中timer,還有一種延時,直接使用NSTimer來配置任務。

這兩種方式都一個共同的前提,就是當前線程裡面需要有一個運行的runloop並且這個runloop裡面有一個timer。

我們知道:隻有主線程會在創建的時候默認自動運行一個runloop,並且有timer,普通的子線程是沒有這些的。這樣就帶來一個問題瞭,有些時候我們並不確定我們的模塊是不是會異步調用到,而我們在寫這樣的延時調用的時候一般都不會去檢查運行時的環境,這樣在子線程中被調用的時候,我們的代碼中的延時調用的代碼就會一直等待timer的調度,但是實際上在子線程中又沒有這樣的timer,這樣我們的代碼就永遠不會被調到。

下面的代碼展示瞭performSelector和dispatch_time的不同

/*
 testDispatch_after 延時添加到隊列
 */
-(void) testDispatch_after{
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3*NSEC_PER_SEC);
    dispatch_after(time, dispatch_get_main_queue(), ^{
        NSLog(@"3秒後添加到隊列");
    });
}
-(void) testDelay{
    NSLog(@"3秒後testDelay被執行");
}
/*
 dispatch_barrier_async 柵欄的作用
 */
-(void) testDispatch_Barrier{
    //dispatch_queue_t gcd = dispatch_queue_create("這是序列隊列", NULL);
    dispatch_queue_t gcd = dispatch_queue_create("這是並發隊列", DISPATCH_QUEUE_CONCURRENT);
    dispatch_async(gcd, ^{
        NSLog(@"b0");
        //這個selector不會執行
        [self performSelector:@selector(testDelay) withObject:nil afterDelay:3];
        //代碼會執行
        //[self testDispatch_after];
    });
    dispatch_release(gcd);
}

在有多線程操作的環境中,這樣performSelector的延時調用,其實是缺乏安全性的。我們可以用另一套方案來解決這個問題,就是使用GCD中的dispatch_after來實現單次的延時調用

發佈留言