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

乡亲! 我在我的应用程序中实现共享caching。 这个想法是在后台从网上获取caching的数据,然后用新检索的数据更新caching和UI。 诀窍是确保线程安全,因为主线程将不断使用caching。 我不想以任何方式修改caching,而其他人可能会使用它。

我的理解是,使用@synchronized来locking对共享资源的访问并不是ObjectiveC中最优雅的方法,因为它陷入了内核,因此相当缓慢。 我一直使用GCD来阅读,而不是一个很好的select(现在让我们忽略它的表弟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. 我在想,只要我只访问共享同一个线程/队列上的共享资源(主要在我的情况下),只有更新主要的UI,那么我将有效地实现线程安全。 那是对的吗?

谢谢!

是。 除了其他考虑之外,不要将读/写工作分stream到主线程上,而应考虑使用私有调度队列。

 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位开发人员,这是最简单的方法,你至less可以得到100个不同的答案(也许更多!)

我所做的和对我来说最好的做法是让一个单身人士做我的形象pipe理。 我使用核心数据,并直接在商店中保存缩略图,但使用文件系统和在“大数据”文件的核心数据中的URL。 核心数据设置为使用新的基于块的接口,因此它可以在自己pipe理的专用线程上完成所有工作。

可能的图像URL通过主线程上的标签进行注册。 其他类可以要求该标签的图像。 如果图像不存在,返回nil,但是这个类设置一个fetchingFlag,使用一个并行的NSOperation耦合到一个NSURLConnection来获取图像,当它获取它时,它会通过接收的图像数据向其线程上的单例消息,而获取该消息的方法使用'[moc performBlock:…]'(不等待)来处理它。

当最终将图像添加到存储库时,moc会使用收到的图像标签在主队列上发送通知。 想要图像的类可以听到这个,当他们得到它时(在主线程上),他们可以再次向moc请求图像,这显然是在那里。