2014-12-06 47 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