如何在没有死锁的情况下同步调度主队列? [英] How to dispatch on main queue synchronously without a deadlock?

查看:213
本文介绍了如何在没有死锁的情况下同步调度主队列?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要同步在主队列上调度一个块。我不知道我目前是在主线程上运行还是不运行。天真的解决方案如下所示:

I need to dispatch a block on the main queue, synchronously. I don’t know if I’m currently running on the main thread or no. The naive solution looks like this:

dispatch_sync(dispatch_get_main_queue(), block);

但如果我目前在主队列上运行的块内,此调用会造成死锁。 (同步调度等待块完成,但块甚至没有开始运行,因为我们正在等待当前块完成。)

But if I’m currently inside of a block running on the main queue, this call creates a deadlock. (The synchronous dispatch waits for the block to finish, but the block does not even start running, since we are waiting for the current one to finish.)

显而易见的下一个步骤是检查当前队列:

The obvious next step is to check for the current queue:

if (dispatch_get_current_queue() == dispatch_get_main_queue()) {
    block();
} else {
    dispatch_sync(dispatch_get_main_queue(), block);
}

这很有效,但很难看。在我至少把它隐藏在一些自定义功能之前,是不是有更好的解决方案来解决这个问题?我强调我不能异步调度块 - 应用程序处于异步调度块将执行得太晚的情况。

This works, but it’s ugly. Before I at least hide it behind some custom function, isn’t there a better solution for this problem? I stress that I can’t afford to dispatch the block asynchronously – the app is in a situation where the asynchronously dispatched block would get executed "too late".

推荐答案

我需要在我的Mac和iOS应用程序中经常使用这样的东西,所以我使用以下帮助函数(最初在这个答案):

I need to use something like this fairly regularly within my Mac and iOS applications, so I use the following helper function (originally described in this answer):

void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}

您可以通过

runOnMainQueueWithoutDeadlocking(^{
    //Do stuff
});

这几乎是你在上面描述的过程,我和其他几位开发人员谈过为自己独立制作这样的东西。

This is pretty much the process you describe above, and I've talked to several other developers who have independently crafted something like this for themselves.

我使用 [NSThread isMainThread] 而不是检查 dispatch_get_current_queue(),因为警告部分对于该功能一旦警告不要使用它进行身份测试和 iOS 6中不推荐使用该呼叫

I used [NSThread isMainThread] instead of checking dispatch_get_current_queue(), because the caveats section for that function once warned against using this for identity testing and the call was deprecated in iOS 6.

这篇关于如何在没有死锁的情况下同步调度主队列?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆