首页 文章

dispatch_sync始终在主线程上调度块

提问于
浏览
10

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

串行队列(也称为专用调度队列)按照将它们添加到队列的顺序一次执行一个任务 . 当前正在执行的任务在由调度队列管理的不同线程(可能因任务而异)上运行 .

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

下面是我用来判断's going on. It is being called inside NSURLConnection' s didReceiveData: 委托方法的代码(我知道我不应该在didReceiveData:delegate方法中做到这一点 - 但这只是一个关注dispatch_sync的示例) . 以下是我可以假设的不同方式作为我的结论的证明:

  • Global Concurrent Queue 上使用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

  • 使用 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相反,我想是这样的 . 有谁知道这是什么一回事?

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

4 回答

  • 5

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

    EDIT

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

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

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

  • 4

    对于背景块,请使用

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

    注意它是_async而不是_sync

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

    dispatch_async(dispatch_get_main_queue(), ^{
        // main thread code
    });
    
  • 0

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

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

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

  • 15

    以下是如何在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

相关问题