线程上下文与线程 ID - 将 CoreData 与异步等待结合使用

本文关键字:线程 等待 结合 异步 上下文 ID CoreData | 更新日期: 2023-09-27 18:33:19

我们在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,知道您不能保证返回相同的上下文,更不用说相同的线程 ID,工程师在顶部代码块中创建的陷阱将导致失败(故意(。

我只想编写根据需要复杂的代码,那么 CoreData 了解 SQLite 后端的单线程性质并且仍然可以轻松地在 C# 中使用异步等待和后台进行编码,这真正需要什么?

谢谢

线程上下文与线程 ID - 将 CoreData 与异步等待结合使用

CoreData 不是线程安全的,您需要为每个线程创建新的 ManagedObjectContext。ManagedObjectContext很便宜,所以它不是矫枉过正。对于使用 moc 的异步/等待。执行(( 应该可以正常工作。