Dispatch Group不会阻止代码运行

时间:2017-04-24 22:07:54

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

我希望调度组中的代码在其他任何事情发生之前完成执行,实际上阻止应用程序执行任何操作,直到完成此代码。但是,我无法让调度组阻止其他代码运行。我已经在堆栈上尝试了几乎所有的建议,但我不知道我在做什么。

我的功能:

- (void)myFunction {

    NSString *myString = @"Hello world";

    dispatch_group_t group = dispatch_group_create();

    NSLog(@"1 entering the dispatch group");

    dispatch_group_enter(group);
    [self doSomething:myString completion:^{
        dispatch_group_leave(group);
        NSLog(@"2 we have left the dispatch group");
    }];
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"3 notifying that the dispatch group is finished");
    }];
    NSLog(@"4 all process are complete, we are done");
}

我希望通过日志语句输出= 1,2,3,4

我通过日志语句得到的输出= 1,4,2,3

为什么我的代码会跳过调度组并在2和3之前打印4?对于我做错的任何建议都表示赞赏。谢谢!

更新

这是我的doSomething方法。我的代码一直挂在dismiss电话上。

doSomething() {

    viewController.dismiss(animated: false completion: { [weak self] in 
        doMoreCode()
    })
}

2 个答案:

答案 0 :(得分:3)

这里什么都没有阻止。 dispatch_group_notify只是说“当小组结束时,运行它。”您打算使用的工具是dispatch_group_wait。如果你想要1,2,3,4,那么你就是这个意思:

- (void)myFunction {

    NSString *myString = @"Hello world";

    dispatch_group_t group = dispatch_group_create();

    NSLog(@"1 entering the dispatch group");

    dispatch_group_enter(group);
    [self doSomething:myString completion:^{
        NSLog(@"2 we have left the dispatch group");
        dispatch_group_leave(group);
    }];

    dispatch_group_wait(group, DISPATCH_TIME_FOREVER);

    NSLog(@"3 notifying that the dispatch group is finished");

    NSLog(@"4 all process are complete, we are done");
}

myFunction当然不能在iOS的主队列上调用(因为它会阻塞,你必须永远不会阻塞主队列)。并且它也不能在doSomething:completion:用于其完成处理程序的同一队列上调用(因为该队列将在dispatch_group_wait处被阻止)。

请记住,dispatch_queue_notify只是将一个块添加到将来某个时间运行的队列中。所以有点不清楚你期望3和4如何工作(在我的例子中我只是折叠它们,但也许你正在寻找别的东西)。

另一种方法是阻止应用程序,并且只安排要运行的东西。在这种情况下,您可以使用主队列。它看起来像这样:

- (void)myFunction {

    NSString *myString = @"Hello world";

    dispatch_group_t group = dispatch_group_create();

    NSLog(@"1 entering the dispatch group");

    dispatch_group_enter(group);
    [self doSomething:myString completion:^{
        NSLog(@"2 we have left the dispatch group");
        dispatch_group_leave(group);
    }];
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"3 notifying that the dispatch group is finished");
    });
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        NSLog(@"4 all process are complete, we are done");
    });
}

请注意,在两个示例中,我都在调用dispatch_group_leave之前记录2。在这个例子中,我还在组完成后注册了两个要在主队列上运行的东西(按顺序)。在这种情况下,myFunction将立即返回(因此可以在主队列上运行),但所有内容都应按顺序打印出来。

答案 1 :(得分:1)

< p>假设< code> doSomething< / code>异步运行,您可以等待组,但通常更好地采用异步模式,例如允许< code> myFunction< / code>要立即返回,但为该方法提供您自己的完成处理程序:< / p> < pre>< code> - (void)myFunctionWithCompletion:(void(^)())completion {     NSString * myString = @" Hello world&#34 ;;     dispatch_group_t group = dispatch_group_create();     NSLog(@" 1进入调度组");     dispatch_group_enter(基);     [self doSomething:myString completion:^ {         dispatch_group_leave(基);         NSLog(@" 2我们离开了调度组");     }];     dispatch_group_notify(group,dispatch_get_main_queue(),^ {         NSLog(@" 3通知调度组已完成");     }); } < /代码>< /预> < p>并像这样使用它:< / p> < pre>< code> [self myFunctionWithCompletion:^ {     NSLog(@" 4所有流程都已完成,我们已完成"); }]; //注意,它来到这里时没有完成,因为它是异步的 < /代码>< /预> < p>显然,在上面的示例中,调度组完全是多余的,但我假设您正在执行多个异步任务,这就是您引入调度组的原因。如果真的只是这一个异步任务,你只需这样做:< / p> < pre>< code> - (void)myFunctionWithCompletion:(void(^)())completion {     NSString * myString = @" Hello world&#34 ;;     [self doSomething:myString completion:^ {         NSLog(@"异步doSomething已完成");         完成();     }]; } < /代码>< /预>