2011-06-03 67 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

相關問題