gpt4 book ai didi

objective-c - 揭秘 NSOperation : concurrent vs non-concurrent and async pattern

转载 作者:太空狗 更新时间:2023-10-30 03:48:19 32 4
gpt4 key购买 nike

是的,我知道。关于 NSOperation 世界有很多问题和答案,但我仍然有一些疑问。我会尝试用两部分的问题来解释我的疑虑。它们相互关联。

在 SO 帖子中 nsoperationqueue-and-concurrent-vs-non-concurrent , Darren 写道

A "concurrent" operation is concurrent on its own; it doesn't need NSOperationQueue to create a thread for it.

但是稍微搜索一下,我发现一个 NSOperation,即使它被声明为并发(通过重写 isConcurrent 方法,例如它返回 YES), 可以添加到 NSOperationQueue。这是什么意思?如果我将一个并发的 NSOperation 添加到一个队列中,到底发生了什么?相反,如果我按原样使用并发操作(不将其添加到队列中)会发生什么情况?

Apple 文档中的注释很清楚:

...operation queues ignore the value returned by isConcurrent and always call the start method of your operation from a separate thread. ...In general, if you are always using operations with an operation queue, there is no reason to make them concurrent.

然后,我对在 NSOperation 中使用异步模式非常感兴趣。我找到了 Dave Dribin ( concurrent operations ) 的一个很好的教程。我明白了他帖子的整体意思。

您不能使用异步模式(例如使用异步 NSURLConnection 请求),因为无法调用委托(delegate)。当 main 完成时,操作被移除。解决方案是重写 start 方法来控制操作生命周期......处理运行循环可能会很痛苦。

现在,试图理解他的帖子,我怀疑是否需要在主线程中运行 start 方法。

- (void)start
{
if (![NSThread isMainThread])
{
[self performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO];
return;
}

// other code here...
}

When dealing with asynchronous APIs, we can begin the asynchronous call on the main thread in start and keep the operation running until it finishes.

你能解释一下为什么吗?

提前谢谢你。

最佳答案

在我看来,NSOperationisConcurrent 属性的命名容易混淆。它的真正意思是“是异步的”。也就是说,当它的 -start 被调用时,它是否快速返回操作是否已经运行完成(异步)?还是直到操作运行完成(同步)才返回?

正如 Apple 的文档所述,当一个操作排队到 NSOperationQueue 时,这并不重要,因为无论如何队列都会在工作线程上调用它。如果它是同步的,那么该工作线程将专用于该操作,直到它完成。如果它是异步的,那么 -start 将在操作完成之前返回,工作线程可以继续做其他工作。

问题是,异步 -start 方法如何确保操作继续进行?这可能需要产生一个单独的线程来完成这项工作,但这是愚蠢的。最好让 NSOperationQueue 处理线程。

更有可能的是,它使用由外部事件驱动的运行循环源。 NSURLConnection 在其异步模式下就是这样的事情。但是,在那种情况下,它必须确保在其上安排运行循环源 a) 的线程将保留下来,并且 b) 将运行其运行循环。不能依赖 NSOperationQueue 的工作线程来完成这两个任务。

同样,您可以为每个这样的操作创建自己的线程,专门用于停留并运行其运行循环,但这是不必要的,而且,再一次,与让操作保持同步并将其排队相比,没有任何优势.

主线程是您已经知道会坚持并运行其运行循环的一个线程。因此,通常最好将运行循环源安排在主线程的运行循环上。唯一要注意的是,为了响应触发运行循环源的处理程序的外部事件,您不要在主线程上执行任何长时间运行的工作。因此,例如,当 NSURLConnection 使用接收到的数据调用您的委托(delegate)方法时,您不会对该数据进行昂贵的计算——或者,如果必须,将昂贵的计算移动到另一个线程。

另一种可能性(中间立场)是创建一个您自己的线程作为许多异步操作的 worker 。因此,不是使用主线程或每个操作一个线程,而是使用一个线程,其工作只是停在其运行循环中。您所有的异步操作都会在该线程的运行循环中自行安排。不过,这种方法并没有太大的必要性或优势。

关于objective-c - 揭秘 NSOperation : concurrent vs non-concurrent and async pattern,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10863157/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com