10

我正在使用 dispatch_sync 执行一个块并且该块被正确执行。但是这个块是在主线程上执行的。根据苹果文档:

串行队列(也称为私有调度队列)按添加到队列的顺序一次执行一项任务。当前正在执行的任务在由调度队列管理的不同线程上运行(可能因任务而异)。

这意味着(或我所理解的)正在执行的当前进程将在单独的线程上运行。

下面是我用来判断发生了什么的代码。它在 NSURLConnection 的didReceiveData:委托方法中被调用(我知道我不应该在 didReceiveData: 委托方法中这样做——但这只是一个关注 dispatch_sync 的示例)。以下是我可以假设的不同方式来证明我的结论:

  1. 在全局并发队列上使用 dispatch_sync

       dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            if ([NSThread isMainThread]) {
                NSLog(@"Main Thread");
            }
            else
                NSLog(@"Not on Main Thread");
    
            //Some Process
        });
    

输出 -

         Main Thread
         Main Thread 
         Main Thread
         // Main Thread printed till didReceiveData: gets called

  1. 在使用 dispatch_queue_create 的自创建队列上使用dispatch_sync

    // Create queue somewhere else like this
    dispatch_queue_t newQueue = dispatch_queue_create("WriteQueue", DISPATCH_QUEUE_SERIAL);
    
    
       dispatch_sync(newQueue, ^{
    
            if ([NSThread isMainThread]) {
                NSLog(@"Main Thread");
            }
            else
                NSLog(@"Not on Main Thread");
    
            //Some Process
        });
    

输出 -

         Main Thread
         Main Thread 
         Main Thread
         // Main Thread printed till didReceiveData: gets called

我在这里有点惊讶,块总是在主线程上执行,或者我错过了什么。因为它似乎与我认为的 Apple Doc 背道而驰。有谁知道这是怎么一回事?

更新:根据其他讨论,我知道 dispatch_sync 在同一个线程上执行一个块(大多数时候),那么为什么苹果文档的语句在某些方面是矛盾的。为什么苹果会说“当前正在执行的任务在由调度队列管理的不同线程(可能因任务而异)上运行。” 还是我还缺少什么?

4

4 回答 4

15

dispatch_sync() 在同一个线程上分派块,这很正常。

编辑

Apple 的文档不仅这样说,还这样说:

作为一种优化,此函数在可能的情况下调用当前线程上的块。

作为旁注(我知道你在谈论同步版本,但让我们更精确一点)我会说 dispatch_async() 也可能导致多个块在同一个线程中执行。

于 2012-12-20T12:20:37.423 回答
5

对于背景块,使用

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    // background code
});

注意它是 _async 而不是 _sync

编辑:同样,要在主线程上执行某些操作,请使用

dispatch_async(dispatch_get_main_queue(), ^{
    // main thread code
});
于 2012-12-20T12:20:59.680 回答
4

重要的是要认识到 Grand Central Dispatch 可以保证提交到主队列的块将在主线程上运行,但提交到任何其他队列的块不能保证块将在哪个线程上执行。

不保证将在哪个线程上调用块;但是,可以保证一次只调用一个提交到 FIFO 调度队列的块。

Grand Central Dispatch 管理线程池并尽可能重用现有线程。如果主线程可用于工作(即空闲),则可以在该线程上执行一个块。

于 2014-08-14T01:41:45.503 回答
0

以下是在 Swift 中执行此操作的方法:

runThisInMainThread { () -> Void in
    // Runs in the main thread
}

func runThisInMainThread(block: dispatch_block_t) {
    dispatch_async(dispatch_get_main_queue(), block)
}

它作为标准功能包含在我的仓库中,请查看:https ://github.com/goktugyil/EZSwiftExtensions

于 2015-12-06T03:34:33.527 回答