每次从我的应用程序调用getter时,我都需要执行大量计算。从getter返回的数据会根据环境不断变化,并且必须进行大量计算才能计算应该返回的内容。因此,我不希望getter中的代码在主线程上运行。这就是我到目前为止所做的:
@interface Calculator ()
@property (nonatomic, strong) dispatch_queue_t calculationThread;
@end
- (dispatch_queue_t)calculationThread {
if (!_calculationThread) {
_calculationThread = dispatch_queue_create("calculation_thread", NULL);
}
return _calculationThread;
}
- (NSArray *)calculation {
// perform calculation in calculationThread, which should not be on main thread and be asynchronous
return arrayContainingCalculations;
}
我基本上想知道如何使用GCD替换评论。我尝试过使用dispatch_queue_t和dispatch_group_notify,但我似乎没有正确实现它。
答案 0 :(得分:2)
我认为使用回调可能是解决此问题的最简单,最有效的方法。
只是不可能只使用一个getter来进行异步计算而不会阻塞它被调用的线程,因为你希望在它执行计算后继续执行它之后调用的代码。
您只需要使用回调创建一个新方法,例如:
-(void) doCalculation:(void(^)(NSArray* result))callback {
dispatch_async(self.calculationQueue, ^{
NSArray* result = self.calculation; // make sure this is doing a synchronous calculation. If it's asynchronous, you'll have to use a semaphore (or another callback!).
if (callback) {
dispatch_async(dispatch_get_main_queue(), ^{ // return to main thread
callback(result);
});
}
});
}
然后您可以在主线程上调用它,如下所示:
[calculator doCalculation:^(NSArray* result) {
textView.text = [result[0] stringValue]; // update UI with new info.
}];
通过这种方式,您可以轻松地将生成的代码与对方法的调用保持一致。
还值得注意的是,你calculationQueue
的吸气者(我将其重命名为,因为当你正在使用队列时,线程这个词会产生误导)并非如此线程安全的。我建议你使用dispatch_once
使其成为线程安全的:
-(dispatch_queue_t) calculationQueue {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_calculationQueue = dispatch_queue_create("calculation_queue", DISPATCH_QUEUE_SERIAL);
});
return _calculationQueue;
}
答案 1 :(得分:1)
您可以使用以下内容将其异步放入队列中。然而问题是该方法将立即返回。
dispatch_async(your_queue, ^{
// Code to be executed on background thread
});
你可能想要的是拥有某种方法calculateWithCompletion
,其中调用者可以定义一个完成完成后可以调用的块。
答案 2 :(得分:0)
正如你在对彼得的评论中所说,你想保留它,这样你就可以调用self.calculation
并执行你的逻辑并同步返回计算。
但是,因为您希望在执行此逻辑时避免锁定UI,所以您希望它在后台线程上执行。
因此,您需要做的只是在dispatch_sync
方法中使用dispatch_async
而不是calculate
。
dispatch_sync
的作用是将任务(包含您的逻辑的块)放到指定的队列(可能应该选择global concurrent queue),然后在操作系统选择的线程上执行您的任务为你(不是主线程)。 dispatch_async
执行相同操作, ,dispatch_async
将您的任务分派到队列后立即继续执行。
dispatch_sync
将阻止当前运行循环中的执行,直到您的任务返回。
这将允许您在后台线程上执行昂贵的逻辑,同时仍然保持同步,以便您可以继续使用self.calculation