用于共享资源访问+UI更新的GCD模式



各位!我正在我的应用程序中实现共享缓存。这个想法是在后台从web获取缓存的数据,然后用新检索到的数据更新缓存和UI。诀窍当然是确保线程安全,因为主线程将持续使用缓存。我不想以任何方式修改缓存,而其他人可能正在使用它。

我的理解是,在ObjectiveC中,使用@synchronized来锁定对共享资源的访问并不是最优雅的方法,因为它会捕获内核,因此相当缓慢。我一直在读到使用GCD是一个很好的选择(现在让我们忽略它的表亲NSOperation),我想弄清楚什么是适合我的情况的好模式

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// download the data in a background thread
dispatch_async(queue, ^{
CacheData *data = [Downloader getLatestData];
// use the downloaded data in the main thread
dispatch_sync(dispatch_get_main_queue(), ^{
[AppCache updateCache:data];
[[NSNotificationCenter defaultCenter] postNotificationName:@"CacheUpdated" object:nil];
});
});
  1. 这真的会像我认为的那样吗?如果是的话,这是目前处理这种情况最干净的方法吗?有一篇博客文章和我说的很接近,但我也想和你核实一下
  2. 我想,只要我只访问同一线程/队列上的共享资源(在我的情况下是main),并且只更新main上的UI,那么我就会有效地实现线程安全。这是正确的吗

谢谢!

是。撇开其他考虑不谈,与其将读/写工作分流到主线程上,不如考虑使用专用调度队列。

dispatch_queue_t readwritequeue;
readwritequeue = dispatch_queue_create("com.myApp.cacheAccessQueue", NULL);

然后更新你的AppCache类:

- (void)updateCache:(id)data {
dispatch_sync(readwritequeue, ^{ ... code to set data ... });
}
- (id)fetchData:... {
__block id data = nil;
dispatch_sync(readwritequeue, ^{ data = ... code to fetch data ...});
return data;
}

然后更新您的原始代码:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// download the data in a background thread
dispatch_async(queue, ^{
CacheData *data = [Downloader getLatestData];
**[AppCache updateCache:data];**
// use the downloaded data in the main thread
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:@"CacheUpdated" object:nil];
});
});

如果你问100名开发人员这里是最优雅的方法,你会得到至少100个不同的答案(也许更多!)

我所做的,对我来说效果很好的,就是让一个singleton类来做我的图像管理。我使用核心数据,并将缩略图直接保存在商店中,但对于"大"文件,我使用文件系统和核心数据中的URL。Core Data被设置为使用新的基于块的接口,这样它就可以在自己管理的专用线程上完成所有工作。

可能的图像URLS在主线程上注册了一个标记。其他类可以请求该标签的图像。如果映像不在那里,则返回nil,但此类设置一个fetchingFlag,使用与NSURLConnection耦合的并发NSOperation来获取映像,当它获取映像时,它会在其线程上用接收到的映像数据向singleton发送消息,而获取该消息的方法则使用"[moc performBlock:…]"(无等待)来处理它。

当图像最终被添加到存储库时,moc在主队列上发送一个带有接收到的图像标签的通知。想要图像的类可以监听这个,当他们(在主线程上)得到图像时,他们可以再次向moc请求图像,这显然是存在的。

最新更新