NSOperationQueue 在完成任务之前获得完成通知
NSOperationQueue gets complete notification before completing tasks
我在我的应用程序中使用 NSOperation
subclass,它将在单个操作中执行以下 4 个任务,我希望所有这 4 个任务在后台线程上 运行 所以我打包成单个 NSOperation
class,这样我就可以轻松地暂停或取消它
任务
- 长时间运行宁计算
- 正在从核心数据中获取数据
- 正在更新到服务器
- 正在更新核心数据
这里每个都必须同步执行,这意味着除了长时间 运行ning 计算之外,每个都依赖于另一个。
代码
// MyOperation.h
@interface MyOperation : NSOperation {
}
@property (nonatomic, getter = isCancelled) BOOL cancelled;
@end
// MyOperation.m
@implementation MyOperation
- (void)cancel
{
@synchronized (self)
{
if (!self.cancelled)
{
[self willChangeValueForKey:@"isCancelled"];
self.cancelled = YES;
[webServiceOperation cancel]
[self didChangeValueForKey:@"isCancelled"];
}
}
}
- (void)main {
if ([self isCancelled]) {
NSLog(@"** operation cancelled **");
return;
}
@autoreleasepool{
[self performTasks];
}
}
- (void)performTasks {
[self calculate:^{
if (self.isCancelled)
return;
[self fetchDataFromCoredata:^{
if (self.isCancelled)
return;
//I am using AFNetWorking for updateWebService task so it shall run on separate NSOperation so it would be like nested NSOPeration
webServiceOperation = [self updateWebService:^{
if (self.isCancelled)
return;
[self updateCoreData:^{
if (self.isCancelled)
return;
}];
}];
}];
}];
}
@end
我假设我没有遵循正确的方法,因为当我使用 KVO
测试此代码时,NSOperationQueue
在它到达计算的完成块之前得到完整的通知。
问题
- 我的做法对吗?
- 如果没有,能否指导我正确的方法?
- 如果这是正确的方法,那么为什么
NSOPerationQueue
在完成块执行之前得到完整的通知?
提前致谢!期待您的回复
实际上只是网络调用需要显式异步,因为您的操作已经 运行 在后台线程上进行。所以你可以简化代码中的块结构,这样就没有那么多嵌套了。
然后您需要正确构造您的操作子类来处理异步内容,如here所述。
如果你想使用 NSOperation 只需按照 "Wain's" 回答你需要按顺序处理任务。
您仍然可以使用 GCD 和避免使用 NSOperation 来处理嵌套块结构。
NSOperation vs Grand Central Dispatch
performTasks 方法实际上不执行任何任务。它将任务分派到队列或调用将任务分派到队列的方法。调度完成后,performTasks 完成,您的 NSOperationQueue 会将其视为已完成,即使任务仍在执行。
我认为没有太多理由在这里使用 NSOperation。只需使用 GCD。
我在我的应用程序中使用 NSOperation
subclass,它将在单个操作中执行以下 4 个任务,我希望所有这 4 个任务在后台线程上 运行 所以我打包成单个 NSOperation
class,这样我就可以轻松地暂停或取消它
任务
- 长时间运行宁计算
- 正在从核心数据中获取数据
- 正在更新到服务器
- 正在更新核心数据
这里每个都必须同步执行,这意味着除了长时间 运行ning 计算之外,每个都依赖于另一个。
代码
// MyOperation.h
@interface MyOperation : NSOperation {
}
@property (nonatomic, getter = isCancelled) BOOL cancelled;
@end
// MyOperation.m
@implementation MyOperation
- (void)cancel
{
@synchronized (self)
{
if (!self.cancelled)
{
[self willChangeValueForKey:@"isCancelled"];
self.cancelled = YES;
[webServiceOperation cancel]
[self didChangeValueForKey:@"isCancelled"];
}
}
}
- (void)main {
if ([self isCancelled]) {
NSLog(@"** operation cancelled **");
return;
}
@autoreleasepool{
[self performTasks];
}
}
- (void)performTasks {
[self calculate:^{
if (self.isCancelled)
return;
[self fetchDataFromCoredata:^{
if (self.isCancelled)
return;
//I am using AFNetWorking for updateWebService task so it shall run on separate NSOperation so it would be like nested NSOPeration
webServiceOperation = [self updateWebService:^{
if (self.isCancelled)
return;
[self updateCoreData:^{
if (self.isCancelled)
return;
}];
}];
}];
}];
}
@end
我假设我没有遵循正确的方法,因为当我使用 KVO
测试此代码时,NSOperationQueue
在它到达计算的完成块之前得到完整的通知。
问题
- 我的做法对吗?
- 如果没有,能否指导我正确的方法?
- 如果这是正确的方法,那么为什么
NSOPerationQueue
在完成块执行之前得到完整的通知?
提前致谢!期待您的回复
实际上只是网络调用需要显式异步,因为您的操作已经 运行 在后台线程上进行。所以你可以简化代码中的块结构,这样就没有那么多嵌套了。
然后您需要正确构造您的操作子类来处理异步内容,如here所述。
如果你想使用 NSOperation 只需按照 "Wain's" 回答你需要按顺序处理任务。
您仍然可以使用 GCD 和避免使用 NSOperation 来处理嵌套块结构。
NSOperation vs Grand Central Dispatch
performTasks 方法实际上不执行任何任务。它将任务分派到队列或调用将任务分派到队列的方法。调度完成后,performTasks 完成,您的 NSOperationQueue 会将其视为已完成,即使任务仍在执行。
我认为没有太多理由在这里使用 NSOperation。只需使用 GCD。