【发布时间】:2010-10-20 06:22:03
【问题描述】:
我有一个 NSInvocationOperation,它会在后台下载并解析一系列 NSXMLDocument 以响应我的 UI。
我停止调用操作的尝试是调用我的 NSOperationQueue 的 cancelAllOperations。但这似乎不会停止调用的执行。
关于如何解决这个问题的任何想法?
【问题讨论】:
标签: objective-c cocoa multithreading pyobjc
我有一个 NSInvocationOperation,它会在后台下载并解析一系列 NSXMLDocument 以响应我的 UI。
我停止调用操作的尝试是调用我的 NSOperationQueue 的 cancelAllOperations。但这似乎不会停止调用的执行。
关于如何解决这个问题的任何想法?
【问题讨论】:
标签: objective-c cocoa multithreading pyobjc
更新: 当我这样做时,仪器显示大量泄漏。 谨慎行事!我把这个留在这里,以防我真的在做某事,而其他人可以弄清楚如何克服泄漏障碍。
这是一个扭曲的想法,我在输入以下内容时正在重新尝试:
将操作设置为 NSInvocationOperation 的 initWithTarget:selector:object: 方法的 object。假设你已经有一个 NSOperationQueue(我们称之为 queue):
NSInvocationOperation *operation = [NSInvocationOperation alloc];
operation = [operation initWithTarget:self selector:@selector(myOperation:) object:operation];
[queue addOperation:operation];
[operation release];
请注意,我们必须将 alloc 分解为它自己的调用。否则我们无法将 object 设置为 operation!
然后,在您的操作方法中,将对象投射回去并根据需要对 isCancelled 进行检查。例如:
- (void)myOperation:(id)object {
NSInvocationOperation *operation = (NSInvocationOperation *)object;
if ([operation isCancelled]) return;
...
}
确保您的选择器在 initWithTarget:... 调用中以冒号结尾,因为您现在将传入一个对象。
到目前为止,一切都很好。现在,如果我可以强制cancelAllOperations,我会知道这是否真的有效。 :)
【讨论】:
您需要检查 NSInvocationOperation isCancelled 是否为 YES。 要在 NSInvocationOperation 中做到这一点,您可以使用 Key Value Observing:
在运行操作时将您的对象添加为 NSInvocationOperation 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;
观察 isCancelled 是否被 NSOperationQueue 的 cancelAllOperations 更改。 您可以在此处设置私有标志,targetMethod 可以检查它并在需要时取消。
【讨论】:
上面的帖子很棒,但更直接地回答了原始问题:您似乎无法停止 NSInvocationOperation 对象,因为它不支持取消。您将不得不对其进行子类化。
【讨论】:
这取决于您的NSOperation 对象的实现,以实际停止它正在执行的操作、清理并在收到通知它已被取消时退出。发送您要取消队列上所有操作的消息将导致队列停止将要运行的新操作出列,并将取消消息发送给当前正在运行的任何操作。
在您的操作的主要方法中,您应该检查isCancelled 并在您实际被取消时处理该状态。
有关详细信息,请参阅线程编程指南中的Creating and Managing Operation Objects。
【讨论】:
NSInvocationOperation时不能这样做(至少以检查isCancelled的标准方式)。