2014-12-06 46 views
0

我們在Xamarin iOS C#項目中使用CoreData。由於併發問題,負責該區域的開發改造,測試了System.Threading.Thread.CurrentThread.ManagedThreadId == 1,如果失敗的異常每下面的代碼拋出代碼:線程上下文與線程ID - 使用CoreData與異步等待

public static NSManagedObjectContext ManagedObjectContext { 
get 
{ 
    if (System.Threading.Thread.CurrentThread.ManagedThreadId == 1) 
    { 
     return MainMOC; 
    } 
    else 
    { 
      if (_context == null) { 
      System.Diagnostics.Debugger.Break(); 
      // Hey, don't ignore this exception, fix it 
      // if you don't fix it, all values coming from core data are suspect 
      throw new Exception("attempting to use a temp context without calling BeginBackgroundContext()"); 
     } 
     return _context; 
    } 
} 

}

這將迫使開發人員使用對於任何後臺代碼模式調用是如下列:

InvokeInBackground(()=> { 

NSManagedObjectContext context = new NSManagedObjectContext(NSManagedObjectContextConcurrencyType.PrivateQueue); 
context.ParentContext = DataSource.MainMOC; 
context.PerformAndWait(() => { 

    try { 

     DataSource.SetContextForThread(context); 

     // update the UI 
     this.InvokeOnMainThread(delegate 
      { 

      // do your code here 

      }); 
    } catch (Exception e) { 

      // log exception here 
    } 

}); 
DataSource.ClearContextForThread(); 

}

是對線程這真的有必要比如創建NSManagedObjectContext,執行代碼,然後保存上下文?這是我的信念,這是過度的,太嚴格。我們應該只關注Thread的語境,而不是測試Thread ID。現在我不確定線程​​上下文和ID是否相同,但我相信它們是不同的。我假設的上下文基本上是UI線程和後臺線程。因此,如果我們在U​​I線程上創建一個上下文,使用.ConfigureAwait(true)方法使用異步等待來確保我們返回被調用的「上下文」,那麼代碼應該仍然工作?現在,如果您使用異步等待知道您不能保證在相同的上下文中返回相同的線程ID,則工程師在頂層代碼塊中創建的陷阱將導致失敗(故意)。

我想只根據需要編寫複雜的代碼,因此CoreData真的需要知道SQLite後端的單線程特性,並且仍然可以輕鬆地使用C#中的異步等待和後臺代碼進行編碼。

謝謝

回答

0

CoreData不是線程安全的,你需要爲每個線程創建新ManagedObjectContext。 ManagedObjectContext很便宜,所以它不是一個矯枉過正的事情。對於異步/等待使用moc.Perform()應該正常工作。

+0

謝謝您的回覆。你可以提供使用mod.Perform()與異步的示例代碼安全地等待,並且在等待Foo()返回時不會導致線程問題嗎?謝謝 – Neal 2014-12-07 18:11:03

+0

@Neal不幸的是,因爲我還沒有爲iOS編寫任何.Net代碼:)(儘管我是.Net開發人員,我使用Objective-C)。無論如何,我會嘗試編寫示例代碼,但我不承諾... – 2014-12-08 13:45:01