意外的核心数据多线程违规 [英] Unexpected Core Data Multithreading Violation

查看:45
本文介绍了意外的核心数据多线程违规的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Apple的并发核心数据调试器.

I'm using Apple's concurrency core data debugger.

-com.apple.CoreData.ConcurrencyDebug 1

-com.apple.CoreData.ConcurrencyDebug 1

我不时得到 __ Multithreading_Violation_AllThatIsLeftToUsIsHonor __ ,甚至我几乎确定没有违反线程.

From time to time I got __Multithreading_Violation_AllThatIsLeftToUsIsHonor__, even I'm almost sure threading is not violated.

这是发生异常的代码的一部分(代码是扩展NSManagedObject的协议的一部分):

This is part of code where exception occurs (code is part of protocol that extends NSManagedObject):

public static func find(arrayBy predicate: NSPredicate, sort: [NSSortDescriptor] = [], limit: Int? = nil) -> [Self] {
    let fetchRequest = NSFetchRequest<Self>(entityName: "\(Self.self)")
    fetchRequest.predicate = predicate
    fetchRequest.sortDescriptors = sort

    do {
        return try Context.current.fetch(fetchRequest) // Exception!!!
    } catch let error {
        Logger.fatal("Failed to perform fetch: \(error)")
        return []
    }
}

代码在上下文的 perform:块中执行.

Code is executed within context's perform: block.

以下是线程信息:

和调试器信息以确认是否在正确的NSManagedContext上执行了该操作:

and debuger info to confirm that perform is executed on the right NSManagedContext:

(lldb) po Context.current
<StoreContext: 0x7f854b556610>

成功提取实体名称:

po fetchRequest.entityName!
"Position"

谓词由纯String对象构成(根本不使用托管对象):

Predicate is constructed of pure String objects (no managed objects used at all):

(lldb) po fetchRequest.predicate!
ANY employees.company.id == "282372"

在这种情况下根本不使用排序描述符:

Sort descriptors are not used at all in this case:

po fetchRequest.sortDescriptors!
0 elements

限制被完全忽略.

我想念什么?有谁知道这里有什么问题吗?

What am I missing? Does anyone has any idea what can be wrong here?

为澄清起见,在分派该块之前设置了 Context.current :

To clarify, Context.current is set just before dispatching the block:

Context.current = managedObjectContext
managedObjectContext.performAndWait {
   //...
}

您可以在屏幕截图中看到线程13 正在队列上运行:NSManagedObject 0x7f854b556610(串行).另外,当发生异常时, Context.current 返回< StoreContext:0x7f854b556610> .通过查看内存地址,可以很容易地推断出块正在正确的队列上执行.

You can see on the screenshot that Thread 13 is running on Queue: NSManagedObject 0x7f854b556610 (serial). Also, when exception occurs Context.current returns <StoreContext: 0x7f854b556610>. By looking at the memory address it's easy to conclude block is executing on the right queue.

推荐答案

在全局状态下存储当前"背景上下文是一种不好的做法.我无法指出您的代码到底在哪里混乱,但是当涉及到多线程时,全局状态可能会发生意外情况.更改您的 find 函数以接受 context 作为参数.这样可以避免使用任何全局状态,并且很可能会解决您的问题.

Storing the "current" background context in a global state is a bad practice. I can't point out where exactly in your code it is messing up, but unexpected things can happen with global state when multithreading is involved. Change your find function to accept a context as a parameter. This will avoid using any global state and is will likely fix your problem.

这篇关于意外的核心数据多线程违规的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆