【问题标题】:Is it dangerous to set off an autoreleased NSOperationQueue?触发自动释放的 NSOperationQueue 是否危险?
【发布时间】:2011-01-30 20:26:06
【问题描述】:

我有一个需要相当长的时间的任务,应该在后台运行。根据文档,这可以使用NSOperationQueue 来完成。但是,我不想保留NSOperationQueue 的类全局副本,因为我真的只将它用于那一项任务。因此,我只是将它设置为自动释放,并希望它在任务完成之前不会被释放。它有效。
像这样:

NSInvocationOperation *theTask = [NSInvocationOperation alloc];
theTask = [theTask initWithTarget:self
                         selector:@selector(doTask:)
                           object:nil];
NSOperationQueue *operationQueue = [[NSOperationQueue new] autorelease];
[operationQueue addOperation:theTask];
[theTask release];

不过,我有点担心。这能保证工作吗?或者operationQueue 可能会在某个时候被释放并带走theTask

【问题讨论】:

  • 不确定答案,但是[NSOperationQueue new] 返回一个自动释放的对象,所以[[NSOperationQueue new] autorelease] 会让你在同一个队列上释放两次,并且应该让你崩溃。此外,永远永远做[[Class alloc] init...] 嵌套。永远不要分开 allocinit。你会省去一些麻烦。
  • [NSObject new] 等价于 [[NSObject alloc] init],所以不会自动释放...
  • 不是您正在寻找的答案,但由于您只希望它用于一项任务,因此[self performSelectorInBackground:@selector(doTask:) withObject:nil] 是一个选项。还是必须是 NSOperation?
  • @Brandon_Bodnar:听起来不错,但由于某种原因,它让我的应用程序窒息。
  • 不自​​动释放队列怎么样,而是在队列末尾添加另一个任务,从而释放它?

标签: objective-c cocoa concurrency autorelease


【解决方案1】:

我猜想 NSOperationQueue 会在它被释放时释放它的任务,但我注意到即使我在添加任务后立即释放队列,任务也会完成并解除分配。也就是说,我不认为我会依赖这种行为 - 通过将 NSOperationQueue 存储在实例变量中(并在 dealloc 中释放它)可以获得更多收益。实例变量将为您提供一种调用队列中其他方法(cancelAllOperations、setSuspended 等)的方法。

【讨论】:

  • 我不想做进一步的交互。如果任务根本没有完成,这甚至不是什么大问题(会发生背景图像看起来有点模糊的情况)。
  • 在这种情况下释放队列可能并不危险,但需要注意的是,由于没有任何文档,因此无法保证它在以后的 SDK 版本中不会有不同的工作方式。我猜 NSOperationQueue 会影响它的保留计数,直到所有任务完成。
【解决方案2】:

你不能使用[NSOperation mainQueue] 对象,这样你就不必担心自动释放它了吗?如果您只需要添加一项对我来说似乎最有意义的任务。

http://developer.apple.com/mac/library/documentation/Cocoa/Reference/NSOperationQueue_class/Reference/Reference.html#//apple_ref/doc/uid/TP40004592-RH2-SW21

【讨论】:

  • 除非他们希望该任务与处理 GUI 事件的主线程并行运行。 mainQueue 串行运行。
【解决方案3】:

无法保证在 NSOperationQueue 仍在工作时释放它是安全的。我怀疑它可能是安全的,并且可能有一天会添加此保证,但现在不存在。但是,等效的 Grand Central Dispatch API确实保证您可以在使用完队列后安全地释放它们,并且只要需要它们就会一直保留它们。因此,如果您在使用 GCD 的平台上,您可以使用它来确保它不会在此期间爆炸。

或者,您可以创建一个包装类来检查队列是否完成,并在队列完成时释放队列和自身。

【讨论】:

    【解决方案4】:

    文档中没有说明释放 NSOperationQueue 时会发生什么。假设不能保证任务会被执行是最安全的。

    【讨论】:

      猜你喜欢
      • 2018-06-14
      • 2010-10-11
      • 2018-06-22
      • 2017-08-21
      • 1970-01-01
      • 1970-01-01
      • 2019-11-28
      • 2010-11-30
      • 1970-01-01
      相关资源
      最近更新 更多