首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >NSBlockOperation和start方法

NSBlockOperation和start方法
EN

Stack Overflow用户
提问于 2012-07-21 12:24:59
回答 2查看 6.8K关注 0票数 2

在检查我的代码时,我发现在很多地方我都假设调用[NSBlockOperationInstance start];会在主线程上启动这个操作。我不知道为什么我会这么想,但无论如何我都不应该这么确定。我检查了文档,但没有找到任何明确提到的线程,块将在其上运行。但是,每次使用start时,都会在块的主体中断言assert([NSThread isMainThread]);,所以我不确定这是否是巧合。有人对这是如何工作的有更扎实的理解吗?

我忘了提到op start是在主线程上调用的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-07-21 13:29:03

好的,这完全取决于你在哪里调用start()。虽然NSBlockOperation会将块出租给其他线程,但start()是同步的,直到提供给NSBlockOperation的所有块都完成后才会返回。

虽然NSBlockOperation将并发执行给定的块,但NSBlockOperation本身并不是并发的(即isConcurrent为false)。因此,根据文档,start()将在调用程序的线程中完整执行start()。

由于调用start()的线程在所有块执行完毕后才会返回,因此让调用线程参与执行并发块的线程池是有意义的。这就是为什么你会看到一些块在调用start()的线程中执行。

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

在相关的注释中,如果您的NSBlockOperation包含单个块,那么该块将始终在调用线程中执行。

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

除此之外,您可以向NSOperationQueue提供任何NSOperation,它将并发执行,因为该NSOperation被提供给一个队列,并且运行该操作的线程调用start()。

就我个人而言,我不认为使用NSBlockOperation比使用dispatch_async()有任何优势,除非我需要使用它的特性。如果只执行一个代码块,只需调用

代码语言:javascript
复制
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ });

如果您想利用NSBlockOperation的特性,但又不想等待它们在当前调用线程中完成,那么这样做仍然是有意义的……

代码语言:javascript
复制
// 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.
    });
});

编辑以将您的评论发送到tc的答案...

如果你调用

代码语言:javascript
复制
op = [NSBlockOperation blockOperationWithBlock:^{assert([NSThread isMainThread])}];
[op start];

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

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

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

然而,上面的“概率”并不是保证(仅仅是因为文档中没有说明)。我猜,一些工程师可能会找到一些理由将单个块旋转到一个并发队列,并让调用线程加入正在另一个线程中执行的操作……但我对此深表怀疑。

无论如何,也许你的困惑来自于NSBlockOperation的文档说它并发地执行块,它确实是这样做的。但是,操作本身不是并发的,所以初始操作是同步的。它将等待所有代码块执行,并且可能(也可能不)在调用线程上执行其中的一些代码块。

虽然不能保证,但我发现只有一个块的NSBlockOperation除了在调用线程上执行之外,不太可能做任何事情。

票数 12
EN

Stack Overflow用户

发布于 2012-07-21 12:34:27

docs明确表示

以默认优先级将添加到块操作的

块分派到适当的工作队列。代码块本身不应该对其执行环境的配置做出任何假设。

我怀疑下面的代码会崩溃:

代码语言:javascript
复制
NSBlockOperation * op = [NSBlockOperation blockOperationWithBlock:^{ sleep(1); }];
[op addExecutionBlock:^{assert([NSThread isMainThread]); }];
[op start];

简单地执行代码块有什么错?

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/11589451

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档