如何停止 NSInvocationOperation?

发布于 2024-07-17 11:37:04 字数 179 浏览 4 评论 0原文

我有一个 NSIncationOperation,它会在后台下载并解析一系列 NSXMLDocuments 以响应我的 UI。

我尝试停止调用操作是调用 NSOperationQueue 的cancellAllOperations。 但这似乎不会停止调用的执行。

关于我如何解决这个问题有什么想法吗?

I have an NSInvocationOperation that would download and parse a series of NSXMLDocuments in the background to my UI responsive.

My attempt at stopping the Invocation operation is to call my NSOperationQueue's cancellAllOperations. But it seems that this won't stop the invocation's execution.

Any ideas on how would I go about this problem?

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

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

发布评论

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

评论(4

浪漫人生路 2024-07-24 11:37:04

更新:当我执行此操作时,仪器显示大量泄漏。 谨慎行事!我将其保留在这里,以防万一我确实在做某件事,而其他人可以弄清楚如何克服泄漏障碍。

这是一个扭曲的想法,当我输入以下内容时,我正在重新尝试:

将操作设置为 NSInitationOperationinitWithTarget:selector:object 的 object方法。 假设您已经有一个 NSOperationQueue (我们将其称为队列):

NSInvocationOperation *operation = [NSInvocationOperation alloc];
operation = [operation initWithTarget:self selector:@selector(myOperation:) object:operation];
[queue addOperation:operation];
[operation release];

请注意,我们必须将分配分解为它自己的调用。 否则我们无法将对象设置为操作

然后,在您的操作方法中,将对象强制转换回来,并根据需要对 isCancelled 进行检查。 例如:

  - (void)myOperation:(id)object {
    NSInvocationOperation *operation = (NSInvocationOperation *)object;
    if ([operation isCancelled]) return;
    ...
  }

确保您的选择器在 initWithTarget:... 调用中以冒号结尾,因为您现在将传入一个对象。

到目前为止,一切都很好。 现在,如果我可以强制cancelAllOperations,我就会知道这是否真的有效。 :)

UPDATE: Instruments shows leaks-a-plenty when I do this. Proceed with caution! I'm keeping this here in case I'm actually on to something and someone else can figure out how to get over the leak hurdle.

Here's a twisted idea, which I'm re-trying as I type this:

Set the operation as the object for NSInvocationOperation's initWithTarget:selector:object: method. Presuming you already have a NSOperationQueue (we'll call it queue):

NSInvocationOperation *operation = [NSInvocationOperation alloc];
operation = [operation initWithTarget:self selector:@selector(myOperation:) object:operation];
[queue addOperation:operation];
[operation release];

Note that we have to break apart the alloc into its own call. Otherwise we can't set object to operation!

Then, within your operation method, cast the object back and sprinkle checks for isCancelled as desired. For example:

  - (void)myOperation:(id)object {
    NSInvocationOperation *operation = (NSInvocationOperation *)object;
    if ([operation isCancelled]) return;
    ...
  }

Make sure your selector ends with a colon back in the initWithTarget:... call, since you'll be passing in an object now.

So far, so good. Now if I can force cancelAllOperations, I'll know if this actually works. :)

心清如水 2024-07-24 11:37:04

您需要检查 NSInitationOperation isCancelled 是否为 YES。
要在 NSInvocableOperation 中执行此操作,您可以使用键值观察:

在运行操作时将对象添加为 NSInitationOperation isCancelled 观察者:

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:<targetObj> selector:@selector(<targetMethod>) object:nil];
[operation addObserver:<targetObj> forKeyPath:@"isCancelled" options:NSKeyValueObservingOptionNew context:nil];
[operQueue addOperation:operation];
[operation release];

然后在 targetObj 中实现

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;

以监视 NSOperationQueue 的 cancellAllOperations 更改 isCancelled 。
您可以在此处设置私有标志,targetMethod 可以检查它并在需要时取消。

You need to check if NSInvocationOperation isCancelled is YES.
To do that in NSInvocationOperation, you can use Key Value Observing:

Add your object as NSInvocationOperation isCancelled observer when running the operation:

NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:<targetObj> selector:@selector(<targetMethod>) object:nil];
[operation addObserver:<targetObj> forKeyPath:@"isCancelled" options:NSKeyValueObservingOptionNew context:nil];
[operQueue addOperation:operation];
[operation release];

Then in targetObj implement

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;

to watch for isCancelled being changed by NSOperationQueue's cancellAllOperations.
You can set a private flag here and targetMethod can check it and cancel if needed.

甚是思念 2024-07-24 11:37:04

上面的帖子很棒,但为了更直接地回答原来的问题:看来您无法停止 NSInvocableOperation 对象,因为它不支持取消。 你必须将其子类化。

The post above is great, but to more directly answer the original question: it appears that you can't stop NSInvocationOperation object because it doesn't support cancellations. You're going to have to subclass it.

随风而去 2024-07-24 11:37:04

NSOperation 对象的实现来实际停止它正在执行的操作、清理并在收到已取消通知时退出。 您想要取消队列上所有操作的消息将导致队列停止将要运行的新操作出队,并将取消消息发送到当前正在运行的任何操作。

在操作的 main 方法中,您应该检查 isCancelled 并在实际取消时处理该状态。

有关详细信息,请参阅 创建和管理操作对象

It's up to the implementation of your NSOperation object to actually stop what it's doing, clean up, and exit when it gets notified that it's been cancelled. Messaging that you want to cancel all operations on the queue will cause the queue to stop dequeueing new operations to run and will send the cancel message to any operations currently running.

In your operation's main method, you should be checking for isCancelled and handling that state when you are actually cancelled.

For more information, see the Creating and Managing Operation Objects in the Threading Programming Guide.

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