Grand Central Dispatch (GCD) 与 PerformSelector - 需要更好的解释
我在我的应用程序中使用了 GCD 和 PerformSelectorOnMainThread:waitUntilDone,并且倾向于认为它们是可以互换的——也就是说,performSelectorOnMainThread:waitUntilDone 是 GCD C 语法的 Obj-C 包装器。我一直认为这两个命令是等效的:
dispatch_sync(dispatch_get_main_queue(), ^{ [self doit:YES]; });
[self performSelectorOnMainThread:@selector(doit:) withObject:YES waitUntilDone:YES];
我错了吗?也就是说,performSelector* 命令与 GCD 命令有区别吗?我已经阅读了很多有关它们的文档,但尚未看到明确的答案。
I've used both GCD and performSelectorOnMainThread:waitUntilDone in my apps, and tend to think of them as interchangeable--that is, performSelectorOnMainThread:waitUntilDone is an Obj-C wrapper to the GCD C syntax. I've been thinking of these two commands as equivalent:
dispatch_sync(dispatch_get_main_queue(), ^{ [self doit:YES]; });
[self performSelectorOnMainThread:@selector(doit:) withObject:YES waitUntilDone:YES];
Am I incorrect? That is, is there a difference of the performSelector* commands versus the GCD ones? I've read a lot of documentation on them, but have yet to see a definitive answer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
正如雅各布指出的,虽然它们可能看起来相同,但它们是不同的东西。事实上,如果您已经在主线程上运行,则它们处理向主线程发送操作的方式存在显着差异。
我最近遇到了这个问题,我有一个通用方法,有时从主线程上的某个东西运行,有时则不运行。为了保护某些 UI 更新,我一直在使用
-performSelectorOnMainThread:
,没有出现任何问题。当我切换到在主队列上使用
dispatch_sync
时,只要在主队列上运行此方法,应用程序就会死锁。阅读有关dispatch_sync
,我们看到:其中
-performSelectorOnMainThread:
我们看到我仍然更喜欢 GCD 的优雅,它提供的更好的编译时检查,以及它在参数方面更大的灵活性等,所以我做了这个小辅助函数来防止死锁:
更新: Dave Dribin 指出了注意事项部分
dispatch_get_current_queue()
,我在上面的代码中改为使用[NSThread isMainThread]
。然后,我用它
来执行需要在主线程上保护的操作,而不必担心原始方法是在哪个线程上执行的。
As Jacob points out, while they may appear the same, they are different things. In fact, there's a significant difference in the way that they handle sending actions to the main thread if you're already running on the main thread.
I ran into this recently, where I had a common method that sometimes was run from something on the main thread, sometimes not. In order to protect certain UI updates, I had been using
-performSelectorOnMainThread:
for them with no problems.When I switched over to using
dispatch_sync
on the main queue, the application would deadlock whenever this method was run on the main queue. Reading the documentation ondispatch_sync
, we see:where for
-performSelectorOnMainThread:
we seeI still prefer the elegance of GCD, the better compile-time checking it provides, and its greater flexibility regarding arguments, etc., so I made this little helper function to prevent deadlocks:
Update: In response to Dave Dribin pointing out the caveats section on
dispatch_get_current_queue()
, I've changed to using[NSThread isMainThread]
in the above code.I then use
to perform the actions I need to secure on the main thread, without worrying about what thread the original method was executed on.
performSelectorOnMainThread:
不使用GCD向主线程上的对象发送消息。以下是 文档说该方法已实现:
并且在
performSelector:target:withObject:order:modes:
上,文档指出:performSelectorOnMainThread:
does not use GCD to send messages to objects on the main thread.Here's how the documentation says the method is implemented:
And on
performSelector:target:withObject:order:modes:
, the documentation states:GCD 的方式被认为更高效、更容易处理,并且仅在 iOS4 及以上版本中可用,而performSelector 在旧版和新版 iOS 中均受支持。
GCD's way is suppose to be more efficient and easier to handle and is only available in iOS4 onwards whereas performSelector is supported in the older and newer iOS.