我们在Xamarin iOS C#项目中使用CoreData。由于并发问题,负责此区域的开发人员设计了测试System.Threading.Thread.CurrentThread.ManagedThreadId == 1
的代码,如果失败,则会根据以下代码抛出异常:
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 CONTEXT而不是测试线程ID吗?现在我不确定线程上下文和ID是否相同,但我相信它们是不同的。我假设的上下文基本上是UI线程和后台线程。因此,如果我们在UI线程上创建一个上下文,请在.ConfigureAwait(true)的方法上使用async await,以确保我们返回被调用的" context"代码应该仍然有效吗?现在,如果您使用异步等待,知道您无法保证在相同的上下文中返回更少相同的线程ID,工程师在顶部代码块中创建的陷阱将导致失败(故意)。
我只想根据需要编写复杂的代码,因此CoreData知道SQLite后端的单线程特性,并且仍然可以使用异步等待和C#中的后台编码轻松编写,真正需要什么?
谢谢
答案 0 :(得分:0)
CoreData不是线程安全的,您需要为每个线程创建新的ManagedObjectContext。 ManagedObjectContext很便宜,所以它不是一种矫枉过正。对于async / await,使用moc.Perform()应该可以正常工作。