NSBlockOperation和start方法

Sno*_*man 2 iphone objective-c ios

在查看我的代码时,我一直在看到,在许多地方我一直在假设调用[NSBlockOperationInstance start];将在主线程上启动此操作.我不知道为什么我这么想,但我不应该这么肯定.我检查了文档,但没有找到任何明确提到该块运行的线程.但是,assert([NSThread isMainThread]);在块的主体中断言确实每次都使用start,所以我不确定这是不是巧合.任何人都对这将如何运作有更深刻的理解?

我忘了提到在主线程上调用[op start].

Jod*_*ins 12

好的,这一切都取决于你调用start()的位置.虽然NSBlockOperation会将块分配给其他线程,但start()是同步的,并且在完成给予NSBlockOperation的所有块之后才会返回.

虽然NSBlockOperation将同时执行它被赋予的块,NSBlockOperation本身就不是并发(即isConcurrent是假的).因此,根据文档,start()将在调用者的线程中完整地执行start().

由于调用start()的线程在所有块都已执行之前不会返回,因此让调用线程参与正在执行并发块的线程池是有意义的.这就是为什么你会在线程中看到一些调用start()的块.

如果您在主线程中看到一个块执行,那么您必须从主线程调用它.

在相关的说明中,如果您的NSBlockOperation包含单个块,则该块将始终在调用线程中执行.

请记住,如果您希望NSOperation完全并发,则必须在子类中实现适当的功能.

除此之外,您可以将任何NSOperation提供给NSOperationQueue,它将同时执行,因为NSOperation被赋予队列,并且运行该操作的线程调用start().

就个人而言,除非我需要使用其功能,否则我认为使用NSBlockOperation优于dispatch_async()没有任何优势.如果您只执行一个块,只需调用即可

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });
Run Code Online (Sandbox Code Playgroud)

如果你想利用NSBlockOperation的功能,但你不想等待它们在当前的调用线程中完成,那么这样做仍然有意义......

// Add lots of concurrent blocks
[op addExecutionBlock:^{ /*whatever*/ }];
// Execute the blocks asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    [op start];
    // Now do what you want after all the concurrent blocks have completed...
    // Maybe even tell the UI
    dispatch_async(dispatch_get_main_queue(), ^{
        // Update the UI now that all my concurrent blocks have finished.
    });
});
Run Code Online (Sandbox Code Playgroud)

编辑 来回应你对tc答案的评论......

如果你打电话

op = [NSBlockOperation blockOperationWithBlock:^{assert([NSThread isMainThread])}];
[op start];
Run Code Online (Sandbox Code Playgroud)

从主线程,然后有一些保证,和一些高概率.

首先,保证[op start]将在调用线程中运行完成.这是因为NSBlockOperation不会覆盖NSOperation的默认行为,该行为指定它不是并发操作.

接下来,如果NSBlockOperation只有一个块,那么它很可能会在调用线程中运行.您几乎与第一个块在调用线程中运行的概率相同.

但是,上述"概率"不是保证(仅因为文档没有说明).我想,有些工程师可能会找到一些理由将该单个块旋转到其中一个并发队列,并让调用线程加入另一个线程中正在执行的操作......但我非常怀疑.

无论如何,也许你的混淆来自于NSBlockOperation的文档说它同时执行块,这样做.但是,操作本身并不是并发的,因此初始操作是同步的.它将等待所有块执行,并且它可能(或可能不)在调用线程上执行它们中的一些.

虽然不能保证,但我发现只有一个块的NSBlockOperation除了在调用线程上执行之外什么都不会做.