【问题标题】:Perform on Next Run Loop: What's Wrong With GCD?在下一个运行循环上执行:GCD 有什么问题?
【发布时间】:2012-05-13 12:01:49
【问题描述】:

我正在尝试这两种方法:

dispatch_async(dispatch_get_main_queue(),^{
    [self handleClickAsync];
});

[self performSelector:@selector(handleClickAsync) withObject:nil afterDelay:0];

响应按钮按下。

第二个允许UIButton 像人们期望的那样突出显示并在下一个运行循环中执行handleClickAsync(我想:肯定是“稍后”)。第一个不允许UIButton实例亮起,直到操作完全完成。

使用 GCD 执行此操作的正确方法是什么,或者performSelector 仍然是唯一的方法?

【问题讨论】:

  • 大概你是从另一个调度队列中调用它的?如果是这样,它将在队列中按顺序运行所有命令。您是否可以在开始操作之前调用此方法?
  • 我不确定。我直接从touchesEnded 调用它,它在UIView 子类(或本例中的UIButton)上免费提供。
  • 我不知道你为什么要在 dispatch_async 和 runloop 的运行之间建立关联......
  • @Paul.s 我假设在运行循环完成之前, UIButton 无法完成更新其内容。这不正确?
  • 是的,但我认为 GCD 只是将任务安排在队列中,我认为它并不关心让 runloop 完成。如果它需要异步完成,那么为什么不在后台队列上运行并在完成时回调主队列?

标签: objective-c ios asynchronous grand-central-dispatch


【解决方案1】:

我相信答案在discussion of the main dispatch queue

此队列与应用程序的运行循环(如果存在)一起工作,以将排队任务的执行与附加到运行循环的其他事件源的执行交错​​。

换句话说,主调度队列设置了一个辅助队列(与UIApplicationMain() 提供的标准事件队列一起,用于处理提交到主队列的块。 当队列中存在块时,运行循环将交替从主事件队列和调度队列中出列任务。另一方面,-performSelector:withObject:afterDelay:delay 参数的 reference 指出:

指定延迟为 0 并不一定会导致选择器立即执行。选择器仍在线程的运行循环中排队并尽快执行。

因此,当你使用执行选择器时,操作在主事件队列的末尾排队,直到队列中它前面的所有内容之后才会执行(大概包括取消突出显示UIButton的代码) 已处理。但是,当您使用主调度队列时,它会将块添加到辅助队列中,然后假设主队列中没有其他块,则可能会立即处理(即在下一个运行循环中)。在这种情况下,取消突出显示按钮的代码仍然位于主事件队列中,而运行循环处理来自辅助块队列的事件。

【讨论】:

  • 这是有道理的,肖恩,并且似乎解释了经验现实。我将等待几天将其标记为已接受,看看还有哪些其他类型的答案。
  • 嗯......希望像@bbum 这样的人会进来验证这些东西,但这不是 SO 的工作方式,所以我会暂时(永远)将其标记为最佳答案。再次感谢。
【解决方案2】:

我认为这会达到你的目的:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
     //bla bla bla
}];

【讨论】:

  • 7 年后的享受
猜你喜欢
  • 1970-01-01
  • 2015-12-16
  • 1970-01-01
  • 2019-03-06
  • 2013-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多