我需要同步在主队列上调度一个块 . 我不知道我目前是在主线程上运行还是不运行 . 天真的解决方案看起来像这样:
dispatch_sync(dispatch_get_main_queue(), block);
但是如果我当前在主队列上运行的块中,则此调用会产生死锁 . (同步调度等待块完成,但块甚至没有开始运行,因为我们正在等待当前块完成 . )
显而易见的下一步是检查当前队列:
if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
block();
} else {
dispatch_sync(dispatch_get_main_queue(), block);
}
这有效,但很难看 . 在我至少将它隐藏在一些自定义功能之前,是否有更好的解决方案来解决这个问题?我强调我不能异步调度块 - 应用程序处于异步调度块将“执行得太晚”的情况 .
3 回答
我需要在我的Mac和iOS应用程序中经常使用这样的东西,所以我使用以下辅助函数(最初在this answer中描述):
你打电话通过
这几乎就是你在上面描述的过程,我和其他一些开发人员进行了交谈,他们为自己独立制作了类似的东西 .
我使用
[NSThread isMainThread]
而不是检查dispatch_get_current_queue()
,因为caveats section for that function一次警告不要使用它进行身份测试和the call was deprecated in iOS 6 .为了在主队列或主线程上进行同步(不一样),我使用:
我最近在UI更新期间开始遇到死锁 . 这引出了我的Stack Overflow问题,这导致我根据接受的答案实现了
runOnMainQueueWithoutDeadlocking
型辅助函数 .但真正的问题是,当从块中更新UI时,我错误地使用了
dispatch_sync
而不是dispatch_async
来获取UI更新的主队列 . 代码完成很容易,事后可能很难注意到 .因此,对于其他人来说,阅读这个问题: if synchronous execution is not required ,只需使用
dispatch_**a**sync
就可以避免您可能会间歇性地发生的死锁 .