意外的核心数据多线程违规 [英] Unexpected Core Data Multithreading Violation
问题描述
我正在使用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屋!