2011-06-03 69 views
1

我正在寻找最佳实践来解决这个难题:如何在后台执行文件导入线程安全吗?如何在后台执行安全文件I/O事务?

我的应用程序有一个文件导入/导出功能,加上核心数据。这意味着,当我将文件导入到我的应用程序中时,我会在Core Data中创建一个条目,并将此文件复制到App的专用目录中。接下来,我将处理该文件,并在应用程序中为其他目的创建一些其他文件。对于iPhone 3G上的每个文件,这些都是大量计算,耗时约0.2秒。

这意味着我在处理某种“交易”时导入。这一切都是使用一个大的FileImportOperation : NSOperation完成的,它遍历所有必须导入的文件,并对列表中的每个文件执行繁重的导入工作。

问题是:后台线程和NSOperation在没有预先警告的情况下被操作系统在短短的1纳秒内杀死。只有主线程最多5秒钟才能快速保存一些工作并退出。

如何确保我从不中途导入文件,使应用程序处于已损坏或已损坏的状态?

从我的角度来看,邪恶的问题是后台线程(包括NSOperation)在用户退出应用程序时立即死亡,而没有任何清理机会。我试图通过编写托管对象来弥补这一点,只有当所有这些文件都已经创建并保存成功时(请记住:每个导入的文件都以不同方式以不同方式复制和处理多次)。但是我仍然可能导致一个不完整的导入,摧毁用户的磁盘。

我对此问题的临时解决方案如下所示:拥有用于通知的NSOperationQueue注册表的对象。当它收到它时,将-cancelAllOperations发送到队列,将所有正在运行的操作标记为已取消。

在这一点上,我卡住了。现在我的NSOperations被标记为取消,但他们仍然必须完成他们当前的内部运行循环并停止。

我的下一个想法是力的主线程等待,直到所有的操作都完成,然后让-applicationWillTerminate:回报。

我希望有一些关于如何实施安全事务的亲建议,以防止在后台导入时将应用程序置于损坏状态。

回答

2

您是否可以以不原子的方式执行导入操作,至少可以重新启动?例如。可重新启动的文件移动可能如下所示:

搜索并删除目标文件夹中的所有文件'* .tmp'。 在源文件夹中查找需要复制的文件 - 找到一个'data.DB' 将文件复制到目标文件夹作为'data.DB.tmp' 将'data.DB.tmp'重命名为'data.DB'

在应用程序启动,搜索并删除所有文件“* .TMP”

再加上基于交易的“核心数据” DB更新(即可以回滚),这种方法可以解决你的问题?

RGDS, 马丁

+0

是的,我做的事情非常相似。有一个“ID文件”被搜索以确定文件是否已被导入。在导入期间,我在我的“事务”中做的最后一件事就是在我创建Core Data中的重要托管对象之后创建此“ID文件”(基本上它具有完全相同的文件名和扩展名)。如果此时出现问题(线程中断),ID文件丢失。在下一次导入期间,所有内容都将被重新覆盖。但它可以用垃圾文件来垃圾文件系统。 – 2011-06-03 13:14:21

1

如果你使用的是iOS 4.x的,你尝试过beginBackgroundTaskWithExpirationHandler

backgroundTaskIdentifier = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     if (backgroundTaskIdentifier != UIBackgroundTaskInvalid) { 
      [app endBackgroundTask:backgroundTaskIdentifier]; 
      backgroundTaskIdentifier = UIBackgroundTaskInvalid; 
     } 
    }); 
}]; 
+0

有道理,但我使用3.2 – 2011-06-03 19:31:55

相关问题