dispatch_async 和 peformSelectorInBackground 的区别

Posted

技术标签:

【中文标题】dispatch_async 和 peformSelectorInBackground 的区别【英文标题】:Difference between dispatch_async and peformSelectorInBackground 【发布时间】:2012-12-24 03:22:40 【问题描述】:

当我推送带有MapViewViewController 时,我需要绘制一条路线。这需要 2 秒,所以我想在另一个线程中进行,因为我不想阻塞 UI。

我用过:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0) ...

如果我在这里画图,大概需要 10 到 15 秒。

如果我使用performSelectorInBackground 方法,路线会在大约 1 或 2 秒后出现。

为什么? PRIORITY_HIGH不应该快吗?

【问题讨论】:

你到底画的是什么? 有点像 GPS 记录器。我有一个带有点的数组,我使用MKPolyline *line = [MKPolyline polylineWithCoordinates:count:],然后使用[self.mapView addOverlay:line]。数组相当大。 :) 是的,我正在后台执行此操作。我考虑过这个问题,但我仍然想试一试,看看它的表现如何。但这并不能解释为什么 performSelectorInBackground 更快,对吧? @VladBogdan:嗯,实际上可能。您是从后台执行此操作的,这是不安全的,因此您实际上是在调用未定义的行为。我敢打赌 performSelectorInBackground 不会更快,只是在 dispatch_async 中执行它实际上并没有立即重绘。例如,如果 -addOverlay: 对当前的 runloop 做了一些事情,那么这在 dispatch_async 中是一个 noop,但它实际上会在 performSelectorInBackground 案例中做一些事情。 @VladBogdan:但重点仍然是在主线程之外执行此操作绝对不安全,您甚至不应该尝试这样做,更不用说尝试对各种后台处理下结论了基于此的机制。 【参考方案1】:

你不应该在后台更新 UI,真的任何事情都可能发生。无论您使用dispatch_async 还是performSelectorInBackground:,处理数据的时间都应该差不多。您遇到的时间差异是 GUI 需要多长时间才能注意到后台发生了变化。我无法解释为什么这两种方法不同,这是一个未记录的实现细节。

处理此问题的正确方法是在后台处理完数据后回调主线程以更新您的 UI。使用 GCD,这可能看起来像这样:

dispatch_queue_t queue = dispatch_get_global_queue( 0, 0 );
dispatch_async( queue, ^
   id result = [self doExpensiveCalculation];
   dispatch_async( dispatch_get_main_queue(), ^
        [self updateUIWithResult: result];
    );
 );

尝试使用 GCD 和 performSelector... 方法实现此模式一次,您应该注意到时间没有差异。

【讨论】:

以上是关于dispatch_async 和 peformSelectorInBackground 的区别的主要内容,如果未能解决你的问题,请参考以下文章

dispatch_async 和 peformSelectorInBackground 的区别

主队列上的 performSelectorOnMainThread: 和 dispatch_async() 有啥区别?

(iOS) dispatch_async() 与 NSOperationQueue

dispatch_sync和dispatch_async的区别

dispatch_async 影响以下代码的性能?

了解 dispatch_async