9

我正在编写一个使用 NSURLConnection 使用异步 Web 请求的应用程序,所以我有多个线程在运行。为了确保我的应用程序的主要逻辑发生在一个线程上,我大量使用performSelectorOnMainThread:waitUntilDone:. 但有时,我在主线程上运行它,这激起了我的好奇心。

如果performSelectorOnMainThread:waitUntilDone:在主线程中被调用?它的行为与 just 一样performSelector:吗?如果waitUntilDone:YES怎么办?如果是的话NO怎么办?

编辑:我发现当waitUntilDone:is时YES,选择器(几乎)立即执行,但我无法弄清楚它何时执行 if waitUntilDone:is NO

4

3 回答 3

14
performSelectorOnMainThread:withObject:waitUntilDone:

是一种在main thread您的application. 这里boolean参数中的值waitUntilDone:指定是否要阻止您指定的main thread执行selector

例如 -

如果你写了这两行——

[self performSelectorOnMainThread:@selector(print) withObject:nil waitUntilDone:YES];

NSLog(@"Hello iPhone");

这是打印方法 -

- (void) print
{
    NSLog(@"Hello World");
}

然后你会得到这个o/p

Hello World
Hello iPhone

所以它首先暂停执行main thread并打印“Hello World”,然后再次执行主线程并打印“Hello iPhone”,因为您YESwaitUntilDone:

但是如果你指定NOwaitUntilDone:那么它会像这样打印 -

Hello iPhone
Hello World

它清楚地表明它提出了执行 a 中指定的请求的请求,selector并且queue随着操作系统的main thread释放,它执行了您的请求。

调用performSelectorOnMainThread:withObject:waitUntilDone:frommain thread或 asecondary thread对其执行没有任何影响,这取决于您在waitUntilDone:

欲了解更多信息 -

NSObject 类参考

于 2013-07-12T05:22:56.213 回答
2
If the current thread is also the main thread, and you pass YES,
the message is performed immediately, otherwise the perform is
queued to run the next time through the run loop.

如果是,则可以在performSelectorOnMainThread:withObject:waitUntilDone:返回之前执行。

我发现当 waitUntilDone: 为 YES 时,选择器(几乎)立即执行,但如果 waitUntilDone: 为 NO,我无法确定它何时执行。

关于运行循环的一点:你的主线程有一个运行循环。这或多或少会阻止线程退出。一个运行循环管理一个待办事项列表。当它的工作完成时,它会暂停该线程的执行一段时间。然后它会稍后醒来,看看是否有工作要做。

工作量可能会有很大差异(例如,它可能会在唤醒时间和执行选择器之间进行一些非常繁重的绘图或文件 i/o。因此,它不是真正精确计时的好工具,但它应该是足以知道它是如何工作的以及实现如何将工作添加到运行循环中。

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Multithreading/RunLoopManagement/RunLoopManagement.html

于 2013-07-12T06:26:36.820 回答
1

如果 waitUntilDone: 为 YES,则它充当立即函数调用。

如果 waitUntilDone: 为 NO,则它将调用与所有其他线程的调用一起排队。

该方法使用通用运行循环模式(即与 NSRunLoopCommonModes 常量关联的模式)在主线程的运行循环上对消息进行排队。作为其正常运行循环处理的一部分,主线程将消息出列(假设它以一种常见的运行循环模式运行)并调用所需的方法。

如上所述,绘图和 I/O 之类的事情优先于队列中的任何事情。一旦主线程有时间在下一个事件循环中进行队列服务,还有一些其他细节使它不像指望先进先出那么简单:

1) dispatch_async() 块忽略模式。

2) 具有特定模式参数的 performSelector 变体——比如事件跟踪——可能优先于在该特定模式下运行的循环中具有默认公共模式参数的变体。

作为一般规则,如果您想要可预测的时序行为,您应该使用不考虑运行循环模式等更高级别考虑的低级别 GCD 调度函数。

于 2013-07-12T13:00:25.010 回答