-performSelector: withObject: afterDelay: 在子线程上调用不运行

问题:

-performSelector: withObject: afterDelay: 在子线程上调用不运行

原因:

分析:

NSRunLoop 对象处理分派事件,但是默认只有主线程的事件循环是开启的 [main.m -> UIApplicationMain() 打开主事件循环]。
NSTimer 基于运行循环进行消息分派。调度 NSTimer 时,其实是要求当前运行循环在某个特定的时间分派某个选择器。运行循环的每个迭代都会对时间进行检查,并触发所有过期的定时器。 -performSelector: withObject: afterDelay: 是通过调度定时器来完成延时的。

结论:

子线程匹配的事件循环默认关闭,无法进行时间检查,无法分派事件。

解决:

1打开子线程匹配的事件循环即可。

- (void) test {

	dispatch_queue_t queue = dispatch_queue_create("iMock", 0);
	dispatch_async(queue, ^{
    	[self performSelector:@selector(testDelay) withObject:nil afterDelay:1.0];
    	[[NSRunLoop currentRunLoop] run];
	});

	NSLog(@"test -> 当前线程: %@",[NSThread currentThread]);
}

- (void) testDelay {
	NSLog(@"testDelay -> 当前线程: %@",[NSThread currentThread]);
}


2017-05-08 13:53:23.728 JJJJ[24528:14443613] 主线程: <NSThread: 0x7a742990>{number = 1, name = main}
2017-05-08 13:53:23.729 JJJJ[24528:14443613] test -> 当前线程: <NSThread: 0x7a742990>{number = 1, name = main}
2017-05-08 13:53:24.733 JJJJ[24528:14443665] testDelay -> 当前线程: <NSThread: 0x7a748050>{number = 2, name = (null)}

2建议使用 dispatch_after 来执行定时任务

- (void) test {

	dispatch_queue_t queue = dispatch_queue_create("iMock", 0);
	dispatch_async(queue, ^{
    	[self performSelector:@selector(testDelay) withObject:nil afterDelay:1.0];
    	[[NSRunLoop currentRunLoop] run];
	});

	NSLog(@"test -> 当前线程: %@",[NSThread currentThread]);

	dispatch_time_t when = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC));
	dispatch_after(when, queue, ^{
    	dispatch_async(queue, ^{
        	// 因为串行队列中 dispatch_async 只会创建一个线程,所以这里的线程和 testDelay 执行的线程相同。
        	// 在串行队列中,testDelay 执行完成之后,再过 5 s 才会执行
        	NSLog(@"dispatch_after -> 当前线程: %@",[NSThread currentThread]);
    	});
	});
}

- (void) testDelay {
	NSLog(@"testDelay -> 当前线程: %@",[NSThread currentThread]);
}


2017-05-08 14:24:38.954 JJJJ[792:18767] 主线程: <NSThread: 0x7a728a50>{number = 1, name = main}
2017-05-08 14:24:38.954 JJJJ[792:18767] test -> 当前线程: <NSThread: 0x7a728a50>{number = 1, name = main}
2017-05-08 14:24:39.956 JJJJ[792:18998] testDelay -> 当前线程: <NSThread: 0x7a73a5e0>{number = 2, name = (null)}
2017-05-08 14:24:44.412 JJJJ[792:18998] dispatch_after -> 当前线程: <NSThread: 0x7a73a5e0>{number = 2, name = (null)}

dispatch_after 延时提交,而不是延时执行。
posted @ 2017-05-08 14:46  上水的花  阅读(469)  评论(0编辑  收藏  举报