dispatch_sync始终在主线程上调度块

时间:2012-12-20 12:17:08

标签: ios objective-c cocoa-touch cocoa grand-central-dispatch

我正在使用dispatch_sync执行一个块,并且块正确执行。但是这个块在主线程上执行。根据Apple Doc:

  

串行队列(也称为私有调度队列)执行一项任务   按照它们添加到队列的顺序。的的   当前执行的任务在不同的线程上运行(可能会有所不同)   从任务到任务)由调度队列管理。

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

以下是我用来判断发生了什么的代码。它在NSURLConnection的 didReceiveData:委托方法中被调用(我知道我不应该在didReceiveData:delegate方法中这样做 - 但这只是一个关注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
        });
    
  2. 输出 -

             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
          });
      
    2. 输出 -

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

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

      更新 :根据其他讨论,我了解到dispatch_sync在同一个线程上执行一个块(大多数时候),那么为什么apple docs的语句是矛盾的从某种角度。为什么apple说“当前正在执行的任务在由调度队列管理的不同线程(可能因任务而异)上运行。” 或者我还缺少什么?

4 个答案:

答案 0 :(得分:15)

dispatch_sync()在同一个线程上调度该块,这是正常的。

修改

Apple的文档不仅说明了这一点,而且还说:

  

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

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

答案 1 :(得分: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
});

答案 2 :(得分:4)

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

  

不保证调用块的哪个线程;但是,保证一次只能调用一个提交给FIFO调度队列的块。

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

答案 3 :(得分: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