我在我的应用中使用NSOperationQueue
和NSOperation
的子类来生成大量数据,因此计算量非常大。
当用户processingQueue.cancelAllOperations()
关闭应用程序时,会调用该应用程序。同样在我的NSOperation
子类中,我覆盖了cancel()
,让它将取消请求转发给执行实际繁重工作的类......
override func cancel() {
AppDelegate.instance.cancelDataGeneration()
super.cancel()
}
但这仍然不够。当我在数据生成过程中关闭应用程序时,它将在Xcode中崩溃。
如何防止崩溃(可能导致数据丢失)?是否可以让应用程序等待关闭,直到所有并发操作都被取消,以及如何完成(如果它甚至可能)?或者通常使用哪些其他方法来解决这个问题?
更新
经过更多调查后,我发现即使在cancel()
中调用NSOperation
之后,processingQueue.cancelAllOperations()
子类上的applicationShouldTerminate
也从未被调用过。所以我添加了一种手动调用取消的方法:
func cancelDataGeneration() {
if let op = AppDelegate.instance._operation {
op.cancel();
}
}
我从applicationShouldTerminate
内部调用此内容(因为applicationShouldTerminate
早于applicationWillTerminate
调用。有趣的是,由于我的AppDelegate是一个Singleton,我必须使用AppDelegate.instance._operation
。我只检查_operation
,当nil
调用时,applicationShouldTerminate
结果为NSOperation
。知道为何会出现这种情况会很有趣。
在任何情况下,取消现在都能正常工作:当应用程序退出时,它将取消数据生成类并退出而不会崩溃...大多数情况下。但我仍然想知道为什么我的cancel()
子类'当我使用processingQueue.cancelAllOperations()
时,{{1}}没有被调用!
答案 0 :(得分:1)
取消操作不会自动将其从队列中删除或停止当前正在执行的操作。对于排队和等待执行的操作,队列必须仍然尝试执行操作,然后才能识别它被取消并将其移动到完成状态。
我会阻止应用程序的主线程,直到NSOperationQueue完成所有工作。
[NSOperationQueue cancelAllOperations]
。
现在,如果您对主线程blocking
感到不舒服,直到当前正在执行的块完成,那么您需要检查一个标志(或者可以在该类上设置NSApplicationDelegate
)哪个信号如果应用程序仍处于活动状态以便继续。如果要终止应用程序,然后阻止fall out
块voluntarily
,这是最干净的方法。
大致如下所示。
void ^(aBlock)(void) = ^void(void)
{
for(NSUInteger i = 0;i < 1000; i++)
{
// heavy processing code. Taking several iterations each second
// At the start of each iteration, check for a flag, to see if to quit
if(_applicationIsShuttingDown) break;
// perform block operation
}
};
并且您的类是NSApplicationDelegate并实现
-applicationWillTerminate:(NSNotification *)aNotification
{
_applicationIsShuttingDown = YES;
}