如何安全地使用GCD处理plist文件?

时间:2013-09-02 12:50:44

标签: objective-c plist grand-central-dispatch

我有一个简单的应用程序,它将数据存储在plist文件中,我需要处理这些数据。因此,存储数据的过程大约需要5秒钟(用于研究建议的人工延迟),同时我需要读取plist的数据(例如在第二个屏幕中显示它)。

首先,我在

中移动了save方法
dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{});

中的读取方法
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{});

但我认为当我在保存过程中尝试读取plist时会导致问题。

无论如何我不需要冻结屏幕。如何在多个线程中正确地为plist进行I / O处理?可能我应该使用两个不同的队列进行读/写?如何同步它们?

2 个答案:

答案 0 :(得分:3)

提示:使用Reader-Writer Access提高性能

•使用并发子系统队列

  • DISPATCH_QUEUE_CONCURRENT

•使用同步并发“读取”

  • dispatch_sync()

•使用异步序列化“写入”

  • dispatch_barrier_async()

示例:

// ...
   _someManagerQueue = dispatch_queue_create("SomeManager", DISPATCH_QUEUE_CONCURRENT);
// ...

您可以在init上创建队列,为nib唤醒等等...如果在同一个实例中可以多次调用该函数,请使用dispatch_once。

然后:

 - (id) getSomeArrayItem:(NSUInteger) index {
    id importantObj = NULL;
    dispatch_sync(_someManagerQueue,^{
        id importantObj = [_importantArray objectAtIndex:index];
     });
   return importantObj;
 }
- (void) removeSomeArrayItem:(id) object {
     dispatch_barrier_async(_someManagerQueue,^{
         [_importantArray removeObject:object];
     });
 }
- (void) addSomeArrayItem:(id) object {
     dispatch_barrier_async(_someManagerQueue,^{
         [_importantArray addObject:object];
     });
 }

通过这种方式,您可以确保每当您阅读信息(例如数组)时,所有“更改”都已经完成或正在“等待” 。每次编写信息时,都不会阻止程序等待操作完成。

您可以使用串行队列,但这会浪费大量处理时间并且不会使读数并行化。这样,如果你使用多个线程,除非它是“写”,否则没有人必须等待另一个线程,这是正确的。

有关以下内容的更多信息:WWDC 2012 Session 712

答案 1 :(得分:1)

您应该使用单个串行队列进行读写。这样,你就可以确保它们不会相互干扰。

例如,在viewDidLoad中,您可以创建队列:

self.queue = dispatch_queue_create(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

然后你可以在保存时使用它:

dispatch_async(self.queue, ^{
    // save
});

阅读时:

dispatch_async(self.queue, ^{
    // read
});

这是串行队列的主要目的之一,用于同步对某些共享资源的访问(请参阅discussion of serial queues)。