Objective c 使用dispatch\u sync强制执行顺序

Objective c 使用dispatch\u sync强制执行顺序,objective-c,multithreading,grand-central-dispatch,dispatch-async,Objective C,Multithreading,Grand Central Dispatch,Dispatch Async,My library向以下用户公开了2个API: -(void) createFile{ dispatch_sync(queueSerial, ^{ //B1 [fileObj createFileInfo:file completion:^(NSError *error){ //execute completion block C1 }]; }); } -(void) readFile:(NSData*)timeStamp{

My library向以下用户公开了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

            });
         }]

    });
}
readFile
createFile
都是异步方法

我通常建议使用我的库的人在
readFile
之前调用
createFile
。但是,无法保证呼叫者最终将如何实现这一点。它通常以以下方式被调用(而我对此没有控制权)

我要做的是确保在执行
完成块C1
后调用
readFile
。我也不想用
createFile
阻塞主线程(但是这个期望可以放宽)。因此,我想要实现的最终结果是:

  • 调用方(我无法控制)调用
    createFile
    并在调用之后立即调用
    readFile
  • createFile
    完全执行,完成块
    C1
    被激发,之后 就是说,
    readFile
    被分派去做它的事情

  • 我怎样才能做到这一点呢?

    感觉就像是在尝试采用一个现有的基于完成处理程序的API,并将其转换为一个串行队列模式。但串行队列只有在调度的块本身是同步的情况下才有意义。(不要将此与
    分派\u 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
        }];
    }];
    
    这意味着在
    setFile
    工作完成之前,它不会执行任何
    getFile
    工作

    说到这里,我想知道你的
    setFile
    getFile
    方法比
    FileObject
    类自己的方法增加了什么附加值


    但关键是,在处理异步方法时,您不能轻松地将它们与简单的串行GCD队列进行协调。如果您想为自己的异步任务分配调度队列行为,那么通常会考虑使用操作队列(或承诺/期货或类似的操作)。.

    我明白你想说什么,但问题是我只能控制
    setFile
    getFile
    方法,而不能控制它们是如何被调用的。所以,我需要绕过这个限制。我能做的最好的事情就是在
    setFileInfo
    完成后强制发送
    getFileInfo
    ,然后你应该编辑你的问题,分享他们是如何被调用的(并解释为什么不能更改他们)。但这里的基本事实是,您不能仅仅采用异步方法并将它们添加到队列中,然后期望队列能够处理它们。从理论上讲,你可以使它们同步,但这确实是一个可怕的想法(有很多原因)。如果您愿意,您可以创建这些异步
    NSOperation
    子类,但这也改变了您的API(虽然有点酷,但需要做更多的工作才能正常工作)。请编辑包含您对API有哪些约束的问题…就这些方法添加的值而言,它们是此类
    FileObject
    中唯一向调用我的流程的客户端公开的方法。我并非完全不反对使用其他方法来实现这一点。只是
    setFile
    方法计算量很大,需要在调用
    getFile
    之前执行,因为它的时间敏感
    时间戳
    expirest这就是我的
    foo
    /
    bar
    示例所做的(不过,我重命名了它们,因为您不应该使用
    set
    前缀命名非访问器方法……如果使用
    set
    启动非访问器方法,您将引入奇怪的警告。)但是只有当计算密集型的
    foo
    完成时,上面才会调用
    bar
    ,但不会阻止调用线程来实现这一点。我更新了我的问题,澄清了限制。在完成块
    C1
    中使用锁定和解锁是个好主意吗?@Rob感谢您的洞察力。我是一个完全的新手(在Obj C中)在这一点上,因此我将尝试从今以后遵循您的建议。
    readFile
    如何传回它读取的数据?它被定义为返回
    void
    ,因此它必须使用完成处理程序或委托模式?@Rob
    readFile
    传递数据(如果有错误值)在完成处理程序C2中。我不确定这些部分是否相关。
    [self foo:^{
        [self bar:^{
            // do whatever you want when its all done
        }];
    }];