簡體   English   中英

與核心數據並發

[英]Concurrency with core data

我正在使用多線程來獲取數據,解析它,創建對象並存儲它們。 在完成所有這些之后,我希望顯示該窗口。 但是現在我有兩個問題:

  • 我陷入僵局
  • 我的障礙不是障礙。

我認為僵局是因為我同時在多個線程中更新了ManagedObjectContext。

  1. 所以我用ConcurrencyType更改了managedObjectContext:

     __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; 
  2. 並為並發隊列創建了一個importContext並分配了parentContext:

     NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; importContext.parentContext = self.managedObjectContext; 
  3. 並將我的操作放入importContext的performBlock中:

     [importContext performBlock:^{ dispatch_async(backgroundQueue, ^{ [myObject methodAWithContext:importContext]; }); dispatch_async(backgroundQueue, ^{ [myObject methodBWithContext:importContext]; }); dispatch_async(backgroundQueue, ^{ [myObject methodCWithContext:importContext]; }); dispatch_barrier_async(backgroundQueueM, ^{ // create barrier to wait for the first 3 threads to be completed. dispatch_async(dispatch_get_main_queue(), ^{ // Save the data from the importContext tot the main context on the main queue NSError *importError = nil; [importContext save:&importError]; [importContext.parentContext performBlock:^{ NSError *parentError = nil; [importContext.parentContext save:&parentError]; }]; [self.window makeKeyAndVisible]; }); }); }]; 

方法1:在每種方法中,我選擇一個對象子集,將其刪除,然后創建新對象並保存。 (我認為刪除比進行提取並檢查要創建的每個對象是否存在都快)。 因此:在方法AI中,選擇所有AObject,將其刪除並創建新的AObject。 在“方法BI”中,選擇所有BObject,將其刪除並創建新的BObject。 在方法CI中,選擇所有CObject,將其刪除並創建新的CObject。

但隨后出現錯誤“ NSManagedObjectContext無法刪除其他上下文中的對象”。

所以方法2:我刪除了刪除。 但是現在我遇到了各種不同的錯誤.....並且屏障不等待其他線程被執行。

Q1:我在做什么錯?

Q2:如何獲得等待3個線程完成的障礙

問題3:如何刪除/清除各個線程上的對象?

(我已經閱讀了Apple發行說明和文檔,但是找不到有關多線程和ManagedContext組合的清晰說明。)

您不能在performBlock調用dispatch_async NSPrivateQueueConcurrencyType類型的托管對象上下文具有自己的調度隊列,用於執行操作。

您嘗試通過將它們移到不同的調度隊列來並行執行多個操作,但這是不可能的。

如果確實必須並行執行多個操作,則必須為每個操作創建一個私有並發類型MOC。

添加:

等待所有操作完成的方法有幾種:

  • 您可以在每個performBlock:的末尾增加一個計數器performBlock:並檢查其值是否為(在您的示例中)3。
  • 您可以創建一個信號量( dispatch_semaphore_create與初始值為零每一個操作),等待所有的信號量( dispatch_semaphore_wait ),並在每年年底的信號旗語performBlock
  • 而且我敢肯定,有更好/更優雅/更復雜的方法可以做到這一點。

但是:在我重新閱讀您的問題時,我發現您嘗試延遲

[self.window makeKeyAndVisible];

直到所有核心數據提取操作完成。 這不是一個好的設計,因為在完成數據導入之前,用戶將看不到任何東西。

更好的設計是立即顯示初始視圖,並在后台操作獲取數據后更新該視圖。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM