使用 dispatch_sync 强制执行顺序

Forcing the order of execution using dispatch_sync

我的库公开了 2 个 API,如下所示:

-(void) createFile{ 

    dispatch_sync(queueSerial, ^{ //B1

     [fileObj createFileInfo:file completion:^(NSError *error){

         //execute completion block C1
     }]; 

    });
}

-(void) readFile:(NSData*)timeStamp{ 

    dispatch_async(queueSerial, ^{ //B2

        [fileObj readFileInfo:fileName completion:^(NSError *error) {
            dispatch_async(queueSerial2, ^{

                //execute completion block C2

            });
         }]

    });
}

readFilecreateFile都是异步方法。

我通常建议使用我的图书馆的人在 readFile 之前调用 createFile。但是,无法保证调用者最终将如何实现它。它通常以下列方式被调用(我无法控制这个

[fileClass createFile];
[fileClass readFile:timeStamp]; 

我想做的是确保 readFilecompletion block C1 执行后被调用。我也不想用 createFile 阻塞主线程(但这种期望可以放宽)。所以我想要达到的最终结果是:

  1. 来电者(我无法控制)调用 createFile 并在调用后立即调用 readFile
  2. createFile 完全执行,完成块 C1 被触发,之后 readFile 被派去完成这件事。

我怎样才能做到这一点?

感觉就像您正在尝试采用现有的基于完成处理程序的 API 并将其塞进串行队列模式中。但是只有当分派的块本身是同步的时,串行队列才有意义。 (并且不要将它与 dispatch_sync 混淆......我们谈论的是块内的任务是否异步,而不是你如何将它分派到你的队列。)但是你正在处理异步方法从其他异步方法调用。

处理采用完成处理程序块的方法时的基本模式是完全消除串行队列(不需要 GCD 队列,或者在任务已经异步时很有用),只使用自己的完成处理程序块方法,并使嵌套最深的块中的最后一次调用调用您自己的完成处理程序。

例如:

- (void)foo:(void (^)())completion {
    [fileObj setFileInfo:file completion:^(NSError *error) {
        // do some other stuff
        completion();
    }];
}

- (void)bar:(void (^)())completion {
    [fileObj getFileInfo:fileName completion:^(NSError *error) {
        // do some other stuff
        completion();
    }];
}

然后你会这样称呼它:

[self foo:^{
    [self bar:^{
        // do whatever you want when its all done
    }];
}];

这意味着它不会执行任何 getFile 操作,直到 setFile 操作完成。

话虽如此,我想知道您的 setFilegetFile 方法在 FileObject 类 自己的方法之外增加了什么附加值。

但关键是在处理异步方法时,你不能简单地用一个简单的串行GCD队列来协调它们。如果你想为本身是异步的任务分配类似行为的行为,那么你通常会考虑使用操作队列(或 promises/futures 或类似的东西)。