Snow Leopard 上的 NSOperationQueue 有多轻?

发布于 2024-08-07 01:28:39 字数 1032 浏览 3 评论 0原文

我正在使用一些代码,这些代码通过各种回调执行一系列异步操作; Snow Leopard 通过块和 GCD 使这变得异常简单。

我从 NSBlockOperation 调用 NSTask,如下所示:

[self.queue addOperationWithBlock:^{
    NSTask *task = [NSTask new];
    NSPipe *newPipe = [NSPipe new];
    NSFileHandle *readHandle = [newPipe fileHandleForReading];
    NSData *inData = nil;
    [task setLaunchPath:path];
    [task setArguments:arguments];
    [task launch];

    while ((inData = [readHandle availableData]) && [inData length]) {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            // callback
        }];
    }

    [task waitUntilExit];
}];

这种方法工作得很好。这就像魔术一样,只要我的回调正确处理并发即可。

现在,我希望能够合并其中一些调用;这是模型对象的“刷新”方法内部,可能需要很长时间才能完成。让用户敲击刷新按钮不应该束缚机器之类的。

我可以在这里看到一个实施困境。我可以创建一大堆队列 - 每种调用类型一个 - 并将它们的并发操作计数设置为 1,然后每当需要新调用时调用 -cancelAllOperations

或者,我可以对当前正在发生的调用进行更多手动簿记,并管理每个模型对象的单个队列(正如我正在做的那样),或者我可以更进一步并使用全局队列。

NSOperationQueue 有多重?创建大量队列是一个糟糕的架构决策吗?有没有更好的方法来合并这些任务?

I'm working with some code that does a bunch of asynchronous operating with various callbacks; Snow Leopard has made this incredibly easy with blocks and GCD.

I'm calling NSTask from an NSBlockOperation like so:

[self.queue addOperationWithBlock:^{
    NSTask *task = [NSTask new];
    NSPipe *newPipe = [NSPipe new];
    NSFileHandle *readHandle = [newPipe fileHandleForReading];
    NSData *inData = nil;
    [task setLaunchPath:path];
    [task setArguments:arguments];
    [task launch];

    while ((inData = [readHandle availableData]) && [inData length]) {
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            // callback
        }];
    }

    [task waitUntilExit];
}];

This approach works perfectly. It's like magic, as long as my callbacks handle the concurrency correctly.

Now, I want to be able to coalesce some of these calls; this is inside a model object's "refresh" method and may take a long time to complete. Having the user pound on the refresh button shouldn't tie up the machine and all that.

I can see an implementation dilemma here. I can make a whole bunch of queues - one per call type - and set their concurrent operation counts to 1 and then call -cancelAllOperations whenever it's time for a new call.

Alternately, I could do some more manual bookkeeping on which calls are currently happening and manage a single queue per model object (as I'm doing) or I could go even further and use a global queue.

How heavy is NSOperationQueue? Is creating a lot of queues a bad architecture decision? Is there a better way to coalesce these tasks?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

但可醉心 2024-08-14 01:28:39

如果您担心性能,请不要猜测:测量并修复您发现的任何瓶颈。添加队列很简单;尝试一下,看看 Instruments 会告诉您对性能的影响。

创建多个队列的主要原因是为了防止您出于某种原因想要启动和停止它们。如果您只是想获得 libdispatch 的好处,只需将操作添加到主队列即可。

If you're concerned about performance, don't guess: measure and then fix any bottlenecks you find. Adding queues is simple; try it and see what Instruments tells you about the effect on performance.

The main reason for creating multiple queues is in case you have some reason for wanting to start and stop them. If you just want to get the benefits of libdispatch, you can get that by just adding operations to the main queue.

失而复得 2024-08-14 01:28:39

您可以添加多个块
到一个 NSBlockOperation ,它将同时执行并且可以通过以下方式取消
取消包含操作。只要您的个人任务不必序列化,这就可能有效。

You can add multiple blocks
to an NSBlockOperation which will be executed concurrently and can be canceled by
canceling the containing operation. As long as your individual tasks don't have to be serialized, this may work.

无妨# 2024-08-14 01:28:39

只需使用任意数量的操作队列即可。它们在这里是为了分隔程序的逻辑部分。我认为只要您不每秒分配数百个队列,您就不必太担心性能。

Just use as many operation queues as you like. They are here to separate logical parts of your program. I don't think you should be too concerned about the performance as long as you aren't allocating hundreds of queues per second.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文