【发布时间】:2015-02-04 20:48:44
【问题描述】:
我们在 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、执行代码、然后保存上下文等线程真的有必要吗?我认为这是矫枉过正且过于严格。我们应该只关心线程上下文而不是测试线程 ID?现在我不确定线程上下文和 ID 是否相同,但我相信它们是不同的。我假设的上下文本质上是 UI 线程和后台线程。因此,如果我们在 UI 线程上创建上下文,请在带有 .ConfigureAwait(true) 的方法上使用 async await 以确保我们返回调用的“上下文”代码应该仍然有效吗?就目前而言,如果您使用 async await 知道您不能保证返回相同的上下文,更不用说相同的线程 ID,工程师在顶部代码块中创建的陷阱将导致失败(故意)。
我只想根据需要编写复杂的代码,那么 CoreData 真正需要什么知道 SQLite 后端的单线程性质,并且仍然可以轻松地使用 C# 中的异步等待和后台进行编码?
谢谢
【问题讨论】:
标签: c# ios multithreading core-data asynchronous