Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios dispatch\u sync始终在主线程上调度块_Ios_Objective C_Cocoa Touch_Cocoa_Grand Central Dispatch - Fatal编程技术网

Ios dispatch\u sync始终在主线程上调度块

Ios dispatch\u sync始终在主线程上调度块,ios,objective-c,cocoa-touch,cocoa,grand-central-dispatch,Ios,Objective C,Cocoa Touch,Cocoa,Grand Central Dispatch,我正在使用dispatch_sync执行一个块,并且该块执行正确。但是这个块是在主线程上执行的。根据苹果文件: 串行队列(也称为专用调度队列)执行一个任务 按它们添加到队列中的顺序进行最新版本 当前正在执行的任务在一个不同的线程上运行(可能会有所不同) 从一个任务到另一个任务),由调度队列管理。 这意味着(或者我所理解的)正在执行的当前进程将在一个单独的线程上运行 下面是我用来判断发生了什么的代码。它是在NSURLConnection的didReceiveData:delegate方法中调用的(

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

串行队列(也称为专用调度队列)执行一个任务 按它们添加到队列中的顺序进行最新版本 当前正在执行的任务在一个不同的线程上运行(可能会有所不同) 从一个任务到另一个任务),由调度队列管理。

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

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

  • 全局并发队列上使用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
        });
    
    // 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
    
             Main Thread
             Main Thread 
             Main Thread
             // Main Thread printed till didReceiveData: gets called
    

  • 在自建队列上使用dispatch\u sync,使用dispatch\u queue\u create

       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
        });
    
    // 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
    
             Main Thread
             Main Thread 
             Main Thread
             // Main Thread printed till didReceiveData: gets called
    

    我在这里有点惊讶,块总是在主线程上执行,或者我遗漏了什么。因为这似乎与苹果公司的做法背道而驰,我想是的。有人知道这是怎么回事吗

    更新:根据其他讨论,我了解dispatch_sync在同一线程上执行一个块(大多数情况下),那么为什么apple docs的声明在某些方面相互矛盾。为什么苹果说“当前正在执行的任务运行在一个由调度队列管理的不同线程上(任务之间可能有所不同)。” 还是我仍然缺少什么?

    dispatch\u sync()在同一个线程上调度块,这很正常

    编辑

    苹果的文档不仅如此,还说:

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


    作为旁注(我知道您谈论的是同步版本,但让我们澄清一下),我要说的是,dispatch_async()也可能导致在同一线程中执行多个块

    对于背景块,使用

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // background code
    });
    
    注意,它是异步的,而不是同步的

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

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

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

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


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

    以下是如何在Swift中执行此操作:

    runThisInMainThread { () -> Void in
        // Runs in the main thread
    }
    
    func runThisInMainThread(block: dispatch_block_t) {
        dispatch_async(dispatch_get_main_queue(), block)
    }
    

    它作为一个标准功能包含在我的回购协议中,请查看:

    我已经提到它只是为了专注于调度同步。我知道我可以使用dispatch_async(dispatch_get_main_queue()@Ismael,如果dispatch_async(dispatch_get_main_queue(),…)来实现它是从主队列中调用的。根据文档,如果我读对了,这将导致死锁。不,它不会导致死锁。很可能它将被添加到主线程队列中,并在线程释放后进行处理。啊,我已经知道了,但它与apple doc相矛盾。我不认为这是一个矛盾,而是一个aff信息(粗体部分)您不能为所用队列选择目标线程,也不能保证其一致性。不过,请针对文档提交一个bug并要求澄清这一点。@JoshuaNozzi我认为您是正确的。我需要提交一个bug并要求clarification@RamyAlZuhouri你在上面引用的观点——它是否也写在文档中iOS,因为我只在Mac开发文档中见过它。@Evol Gate它在两个文档中都有写:iOS和OS X。可能NSThread不知道队列…@vikingosegundo“不知道”是什么意思?NSThread是一个旧的软件,而dispatch_queues是新的。也许NSThreads只是不知道queues,或者至少不完全知道—我不知道,只是一个想法。或者正如Ramy在他的编辑中指出的那样,您的示例不能像您预期的那样工作。@quelish您的答案有意义吗……您想分享您的评论参考吗苹果文档链接?Thanks@NisarAhmad,它在标题中:以及
    人工调度队列\u创建
    @quelish:如果主线程可能在主队列以外的其他队列中使用,是否意味着当时关联的当前循环是MainRunLoop?(我知道循环与线程关联)