Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/26.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
Objective c GCD将在主线程中执行任务_Objective C_Grand Central Dispatch - Fatal编程技术网

Objective c GCD将在主线程中执行任务

Objective c GCD将在主线程中执行任务,objective-c,grand-central-dispatch,Objective C,Grand Central Dispatch,我有一个可能来自任何线程的回调。当我得到这个回调时,我想在主线程上执行某个任务 我是否需要检查我是否已经在主线程上,或者在调用下面的代码之前不执行此检查是否有任何惩罚 dispatch_async(dispatch_get_main_queue(), ^{ // do work here }); 不,您不需要检查是否已经在主线程上。通过将块分配到主队列,您只需将块安排在主线程上串行执行,这在运行相应的运行循环时发生 如果您已经在主线程上,则行为是相同的:该块被调度,并在主线程的运行循环运

我有一个可能来自任何线程的回调。当我得到这个回调时,我想在主线程上执行某个任务

我是否需要检查我是否已经在主线程上,或者在调用下面的代码之前不执行此检查是否有任何惩罚

dispatch_async(dispatch_get_main_queue(), ^{
   // do work here
});

不,您不需要检查是否已经在主线程上。通过将块分配到主队列,您只需将块安排在主线程上串行执行,这在运行相应的运行循环时发生


如果您已经在主线程上,则行为是相同的:该块被调度,并在主线程的运行循环运行时执行。

对于上面描述的异步调度情况,您不需要检查是否在主线程上。正如Bavaries所指出的,这将只是排队在主线程上运行

但是,如果您尝试使用
dispatch\u sync()
执行上述操作,并且回调位于主线程上,则应用程序将在此时死锁。我在回答中描述了这一点,因为当从
-performselectornmainthread:
移动一些代码时,这种行为让我感到惊讶。正如我在这里提到的,我创建了一个助手函数:

void runOnMainQueueWithoutDeadlocking(void (^block)(void))
{
    if ([NSThread isMainThread])
    {
        block();
    }
    else
    {
        dispatch_sync(dispatch_get_main_queue(), block);
    }
}
如果您所使用的方法当前不在主线程上,它将在主线程上同步运行一个块,如果在主线程上,则只内联执行该块。您可以使用如下语法来使用:

runOnMainQueueWithoutDeadlocking(^{
    //Do stuff
});

正如前面提到的其他答案一样,从主线程进行dispatch_async是可以的

但是,根据您的用例,有一个副作用,您可能会考虑到一个缺点:因为块被安排在队列中,直到控件返回到运行循环,它才会执行,这将延迟块执行的效果。 比如说,

NSLog(@"before dispatch async");
dispatch_async(dispatch_get_main_queue(), ^{
    NSLog(@"inside dispatch async block main thread from main thread");
});
NSLog(@"after dispatch async");
将打印:

before dispatch async
after dispatch async
inside dispatch async block main thread from main thread

因此,如果您希望块在外部NSLog之间执行,dispatch\u async将不会帮助您。

不,您不需要检查是否在主线程中。以下是如何在Swift中执行此操作:

runThisInMainThread { () -> Void in
    runThisInMainThread { () -> Void in
        // No problem
    }
}

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

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

问题是是否存在“不执行此检查的惩罚”。。。我认为在没有必要的情况下使用异步调度会对性能造成影响,或者说这很简单?@Yar我认为在大多数情况下不会对性能造成明显影响:GCD是一个轻量级库。也就是说,我把这个问题理解为:“根据下面的代码,我是否需要检查我是否在主线程上?”但是,您需要检查是否使用dispatch_sync。否则会出现死锁。如果您在主队列上,并将
async
调度回主队列,它将运行,但这可能会打乱操作的预期时间。例如
viewDidLoad()
中的UI代码。为什么不将其称为类似“runnonmainqueuesync”的名称呢?事实上,它可能会死锁,而不会死锁,这是我不想在我的代码中出现的情况。谢谢,一如既往地使用+1。@Yar-我只是给它起了这个名字,这样我就清楚了为什么我不只是在主队列上同步触发块,而不是使用这个helper函数。这更像是对我自己的提醒。这个函数仍然有可能死锁。主队列同步>其他队列同步>主队列将死锁。@hfossli-True,它不会处理所有情况。在我的使用中,我总是从后台串行队列上的异步调度或主线程上的内联代码中调用。我想知道
dispatch\u set\u specific()
是否会在您描述的情况下有所帮助:[NSThread isMainThread]经常返回YES,在GCD编程中检查这种情况不安全。需要说明的是,这是一件需要考虑的重要事情,因为您需要检查,这意味着代码可能在主线程中运行,也可能不在主线程中运行。已经在主线程中的线程将按该顺序运行,否则无法保证这一点。因此,在涉及多线程编程时,应避免将代码设计为按特定顺序运行。尝试使用异步回调方式。五年后,我仍然记不住GCD块的语法,每次都在这里结束。@SpaceTrucker-这与我在这一页上的原因相同:D9年后,我仍然从这一页复制语法。要复制的代码在问题中,而不是答案中!这就是问问题如此重要的原因。:)差不多10年后。。。