ios在后台线程上写入磁盘

ios在后台线程上写入磁盘

本文介绍了ios在后台线程上写入磁盘的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在通过调用

dispatch_async(my_queue,^{
   [self writeToRoot:filename data:data];
};

- (BOOL)writeToRoot:(NSString *)path data:(NSData *)content
{
    NSString *fullPath = [[self rootPath] stringByAppendingPathComponent:path];

    NSString *pathWithoutFile = [fullPath stringByDeletingLastPathComponent];

    BOOL directoryExists = [[NSFileManager defaultManager] fileExistsAtPath:pathWithoutFile];

    if (!directoryExists) {
        NSError *error = nil;
        [[NSFileManager defaultManager] createDirectoryAtPath:pathWithoutFile
                                  withIntermediateDirectories:YES
                                                   attributes:nil error:&error];
        NSParameterAssert(error == nil);
    }

    return [content writeToFile:fullPath atomically:NO];
}

我这样做是因为它不会阻塞主线程.我的问题是如何确保线程安全.在执行此后台操作时,当我尝试通过调用以下命令从磁盘读取文件时会发生什么情况:

I am doing this so as it would not block the main thread. My question is how to ensure thread safety. while this background operation is being carried out, what happens when I try to read from disk the file by calling:

[NSData dataWithContentsOfFile:fullPath];

内容会被破坏吗?还是写操作会锁定文件,而读操作将等到写操作完成?

Will be content be corrupted?OR will the write operation lock the file and the read operation will wait until the writing is completed?

推荐答案

我倾向于对my_queue进行dispatch_sync的读取操作,以确保线程安全(假设它是串行队列).您还可以使用各种(例如锁或@synchronized指令),但是考虑到您已经为文件交互设置了队列,使用该串行队列可能最简单.

I'd be inclined to dispatch_sync your read operation to the my_queue to ensure thread safety (assuming that it's a serial queue). You could also use any of the various synchronization tools (such as locks or @synchronized directive), but given that you already have your queue set up for file interaction, using that serial queue is probably easiest.

部分.

顺便说一句,如果要保存在后台队列中(这意味着保存操作可能足够慢,不足以证明在后台进行保存是合理的),因此请确保您请求一点时间来完成操作在保存操作正在进行时,以防应用本身中断(即用户点击物理主页按钮,打进电话等)的操作.为此,您可以在分派保存操作之前调用beginBackgroundTaskWithExpirationHandler,并在完成后调用endBackgroundTask:

By the way, if you're saving in a background queue (which means that the save operation is presumably slow enough to justify doing it in the background) it might be prudent to make sure that you request a little time to complete the operation in case the app, itself, is interrupted (i.e. the user taps the physical home button, a call comes in, etc) while the save operation is in progress. You do this by calling beginBackgroundTaskWithExpirationHandler before you dispatch the save operation, and call endBackgroundTask when it's done:

UIApplication *application = [UIApplication sharedApplication];

// get background task identifier before you dispatch the save operation to the background

UIBackgroundTaskIdentifier __block task = [application beginBackgroundTaskWithExpirationHandler:^{
    if (task != UIBackgroundTaskInvalid) {
        [application endBackgroundTask:task];
        task = UIBackgroundTaskInvalid;
    }
}];

// now dispatch the save operation

dispatch_async(my_queue, ^{

    // do the save operation here

    // now tell the OS that you're done

    if (task != UIBackgroundTaskInvalid) {
        [application endBackgroundTask:task];
        task = UIBackgroundTaskInvalid;
    }
});

这将确保您的保存操作有很大的机会成功完成,即使该应用程序被中断了.

This will ensure that your save operation has a fighting chance to successfully complete, even if the app is interrupted.

而且,正如Jsdodgers指出的那样,您可能也想执行原子写入.

And, as Jsdodgers points out, you probably want to perform an atomic write, too.

这篇关于ios在后台线程上写入磁盘的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-21 10:15