代码之家  ›  专栏  ›  技术社区  ›  xyzzycoder

异步块的推荐设计模式?

  •  6
  • xyzzycoder  · 技术社区  · 13 年前

    我正在开发一款具有高度异步设计的iOS应用程序。在某些情况下,单个概念性“操作”可能会将许多子块排队,这些子块将异步执行并异步接收它们的响应(对远程服务器的调用)。这些子块中的任何一个子块都可能在错误状态下完成执行。如果任何子块中发生错误,则应取消任何其他子块,错误状态应渗透到父块,并执行父块的错误处理块。

    我想知道在这样的环境中工作可能会推荐哪些设计模式和其他技巧?

    我知道GCD的dispatch_group_async和dispatch_ggroup_wait功能。这可能是该应用程序设计中的一个缺陷,但我在dispatch_group_async方面运气不佳,因为该组似乎对子块不“敏感”。

    提前感谢!

    3 回复  |  直到 13 年前
        1
  •  5
  •   Sam Clewlow    13 年前

    有一个WWDC视频(2012)可能会帮助你。它使用自定义 NSOperationQueue 并将异步块放置在内部 NSOperations 这样您就可以保留块的句柄并取消剩余的排队块。

    一个想法是让子块的错误处理在处理 操作队列 。然后该课程可以适当地取消其余部分。这样子块只需要知道自己的线程和主线程。这是视频链接

    https://developer.apple.com/videos/wwdc/2012/

    该视频名为“在iOS上构建并发用户界面”。相关的部分主要在后半部分,但你可能想仔细观察整个事情,因为它很好地将其放在上下文中。

    编辑:

    如果可能的话,我建议在嵌入式块中处理响应,这样可以很好地将其封装在一起,这就是我 认为 你在追求。。

    //Define an NSBlockOperation, and get weak reference to it
    NSBlockOperation *blockOp = [[NSBlockOperation alloc]init];
    __weak NSBlockOperation *weakBlockOp = blockOp;
    
    //Define the block and add to the NSOperationQueue, when the view controller is popped
    //we can call -[NSOperationQueue cancelAllOperations] which will cancel all pending threaded ops
    [blockOp addExecutionBlock: ^{
    
        //Once a block is executing, will need to put manual checks to see if cancel flag has been set otherwise
        //the operation will not be cancelled. The check is rather pointless in this example, but if the
        //block contained multiple lines of long running code it would make sense to do this at safe points
        if (![weakBlockOp isCancelled]) {
    
            //substitute code in here, possibly use *synchronous* NSURLConnection to get
            //what you need. This code will block the thread until the server response
            //completes. Hence not executing the following block and keeping it on the 
            //queue.  
            __block NSData *temp;
            response = [NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]];
    
            [operationQueue addOperationWithBlock:^{
                if (error) {
                      dispatch_async(dispatch_get_main_queue(), ^{
                            //Call selector on main thread to handle canceling
                            //Main thread can then use handle on NSOperationQueue
                            //to cancel the rest of the blocks 
                      });
                else {
                     //Continue executing relevant code....      
                }
            }];
        }
    }];
    [operationQueue addOperation:blockOp];
    
        2
  •  1
  •   xyzzycoder    10 年前

    自从发布这个问题以来,我遇到的一种模式是使用信号量将异步操作更改为同步操作。这非常有用。这篇博客文章更详细地介绍了这个概念。

    http://www.g8production.com/post/76942348764/wait-for-blocks-execution-using-a-dispatch-semaphore

        3
  •  -1
  •   deleted_user    13 年前

    有很多方法可以在cocoa中实现异步行为。

    GCD、NSOperationQueue、performSelectAfterDelay,创建自己的线程。有适当的时间使用这些机制。这里讨论的时间太长了,但你在帖子中提到的一些事情需要解决。

    如果任何子块中发生错误,则应取消任何其他子块,错误状态应渗透到父块,并执行父块的错误处理块。

    块不能将错误添加到堆栈中。时期

    推荐文章