【问题标题】:How to ensure completion of a async operation before continuing with execution如何在继续执行之前确保完成异步操作
【发布时间】:2014-04-17 06:17:44
【问题描述】:

我正在构建一个 iOS 应用程序,其代码的某些部分依赖于从特定任务返回的成功/失败值。这些任务涉及来自库的回调。我希望仅在回调返回成功/失败后才返回此任务的返回值。但是由于我编写了一个顺序代码,因此甚至在回调返回成功/失败之前就返回了返回值。

我研究过使用模态视图控制器,据我了解,我可以让任务从这个视图控制器执行,然后返回代码。

但这也不符合我的要求,因为当执行启动回调序列的代码时,我不希望显示新的视图控制器。虽然有一定的回调需要我提示用户信息。我在弹出框中执行此操作,并且我考虑在弹出框模式中制作视图控制器。但是回调仍然是主线程的一部分,当我的弹出框以模态方式呈现时我不会收到它们(?)。

以我目前对这些概念的理解,我不知道如何继续。在 iOS 中有没有办法做到这一点?

编辑: 代码做了这样的事情

//In CustomTableViewController

-(void) someFunc
{
   ENUM_NAME code = [TaskController startTheTask:args];
   if(code == SUCCEEDED)
   {
      //Do Something
   }
   if(code == FAILED)
   {
      //Do Something Else
   }
}

//In TaskController

-(ENUM_NAME) startTheTask:args
{
   startWorkflow(args); //This function registers callback function with the library. 
   return finalCode; //This is returned even before it is set to SUCCEEDED/FAILED
}

-(void) onCallback:params
{
    MSG_TYPE msg = [params getMsg];

    if(msg == TASK_FAILED)
       finalCode = FAILED;
    if(msg == TASK_SUCCEEDED)
       finalCode = SUCCEEDED;
    if(msg == TASK_SHOW_PROMPT)
    {  
       [PopOverController showPopOver];
    }
}

-(void) onUserInfoAdded
{
    //This is called when Confirm is clicked in the popover
    continueWorkflow(params); //asks for the next callback to happen
}

-(void) onCancleClicked
{
    //This is called when Popover is dismissed without entering Info
    cancleWorkflow(params); //asks for result of the workflow through callback
}

【问题讨论】:

  • 你可以使用委托方法,一旦你的异步方法完成就会被触发。

标签: ios modalviewcontroller presentmodalviewcontroller


【解决方案1】:

您可以使用 GCD。例如:

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_group_t group = dispatch_group_create();

    dispatch_group_enter(group);
    dispatch_group_async(group, queue, ^{           
         //put one process here
         dispatch_group_leave(group);  //when done
    });

    dispatch_group_enter(group);
    dispatch_group_async(group, queue, ^{           
         //put another process here
         dispatch_group_leave(group); //when done
    });

    // All updates finished
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{
         // add last steps here after all processess are finished
    });

    dispatch_release(group);

【讨论】:

    【解决方案2】:

    您可以使用信号量来延迟执行,直到块返回:

    __block dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
    __block NSData *dataFromTheBlock = nil;
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // block implementation
        // dataFromTheBlock = some data;
        dispatch_semaphore_signal(semaphore);
    });
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
    

    【讨论】:

    • 感谢您的回答。关于我发布的代码,TaskController 中的所有函数都应该是这个块的一部分吗?在没有onCallback 函数作为此块的一部分的情况下,还有其他方法可以获取回调吗?
    • 区块不是强制的。关键是你可以用dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); 阻塞当前线程,并在你调用dispatch_semaphore_signal(semaphore); 时继续执行。当然,这两个调用不能在同一个线程上,因为它会无限期地阻塞那个线程。
    • 阻塞线程以从异步任务中获取结果并在结果最终可用后继续程序是没有意义的。实际上,这是一种代码气味。你可以看看朱莉的回答,这是一种合理的方法。
    • @CouchDeveloper 我同意,阻塞主线程不是很健康,但是如果你必须在一个方法中返回一些东西,而这个东西来自一个块,会发生什么?在执行该块之前,您将不得不等待并阻塞线程,对吗?对于 OP 所问的“如何确保在继续执行之前完成异步操作”,我相信这是“在继续执行之前”部分的一个很好的答案。但是,朱莉的回答向我展示了一些我不知道的事情,所以感谢您指出这一点。
    • @Levi 为了获得异步方法的最终结果并继续执行程序,您定义了一个“延续”。 “延续”可以是由 call-site 定义的 Block,基本上包含在任务完成时执行 的代码。当任务完成时,它调用这个块并将其结果作为参数传递给块。因此,块定义如何结果可用时继续程序。这是一种常见的异步模式,完全避免了阻塞线程。
    猜你喜欢
    • 2013-11-21
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多