Ios dispatch_get_current_queue()已弃用,是否有安全CoreData的替代方案?
许多人问了一个标题相似但目的却截然不同的问题: CoreData要求您跟踪当前队列、当前线程和当前NSOperationQueue(如果您是一个NSOperation),如果您允许来自其他类的方法调用(默认情况下,每个类都允许)。关于这一点没有“可能”:这是一个严格的要求 这很好,通常很容易确保:Ios dispatch_get_current_queue()已弃用,是否有安全CoreData的替代方案?,ios,core-data,grand-central-dispatch,Ios,Core Data,Grand Central Dispatch,许多人问了一个标题相似但目的却截然不同的问题: CoreData要求您跟踪当前队列、当前线程和当前NSOperationQueue(如果您是一个NSOperation),如果您允许来自其他类的方法调用(默认情况下,每个类都允许)。关于这一点没有“可能”:这是一个严格的要求 这很好,通常很容易确保: NSAssert( [NSThread currentThread].isMainThread || myPrivateQueue == dispatch_get_current_queue(), @
NSAssert( [NSThread currentThread].isMainThread || myPrivateQueue == dispatch_get_current_queue(), @"You tried to call this method from an external thread, or a queue other than my internal private queue. That's not legal, and will cause data corruption" );
…除了苹果已经不赞成dispatch_get_current_queue(),显然是“因为人们滥用它来绕过GCD中缺失的功能/他们不理解的GCD位”
注意:从苹果的标题评论来看,我上面对dispatch_get_current_queue()的使用似乎是正确的,没有滥用:关键是我正在检查队列是否是我创建的私有队列(苹果声称这是可以接受的用法)
撇开仅仅因为实现中的缺陷而否定某个东西的智慧不谈:(…有没有人找到了一个解决办法,让苹果删除这个问题。特别是:有了CoreData,你必须跟踪队列-还有其他方法吗
(这很重要,因为:对于CoreData,如果您允许某些东西意外调用这样的方法,您不会得到“崩溃”,您将得到“数据损坏,在将来的某个时候,当修复它为时已晚时会出现”)
performBlock
始终在正确的线程中运行它。只需使用:
[yourManagedObjectContext performBlock:^{
//do your stuff here
}];
您不再需要跟踪当前上下文,因为您的MOC知道哪个线程首先触发此MOC。当您使用
performBlock
或performBlock和wait
时,您是安全的。在我的特定情况下,我将所有performBlock调用替换为:
…因此,就目前而言,就我的目的而言:这已被证明是一个很好的解决方案。我不认为这是对这个问题的“正确”的一般性答案,但…我向任何发现“performBlock”并不像表面上那样是万灵药的人推荐它。好主意,但它似乎在复杂情况下的线程锁定和性能方面存在问题-通过“问题”我的意思是“可能是CoreData问题,也可能是我们的代码库中的bug,可能两者都有”。我的第一步是开始自由地断言,以找出为什么偶尔会出现“CoreData在一个互斥体上挂起数十秒,而互斥体似乎没有争议”…因此我试图消除我们对“所有事情都始终使用performBlock”的依赖并找出实际发生/未发生的事情“总是
performBlock:
for everything”几乎是一种推荐的快速处理方式。dispatch\u get\u current\u queue()
基本上是无用的,因为libdispatch的工作方式——有少量的“全局”队列和其他队列最终以要在这些队列上执行的操作为目标。这会导致该调用无效,因为当前队列是哪个?它在哪个队列上排队?还是它在哪个全局队列上执行。排队器是您在哪个队列上的仲裁者。在这种情况下,performBlock:
是排队器,并且是唯一的方法我知道你在那个队列中。对于我在这里询问的应用程序,我一直在使用dispatch\u queue\u set\u specific()
和dispatch\u get\u specific()
,它在识别特定队列方面工作得很好。Jody对答案的评论提到在核心数据中使用类似的东西。@BradLarson dispatch\u get\u specific()非常有趣,谢谢。我不确定当您不在块内时调用它会发生什么(在正确的执行中,您可能会这样做,但我想知道当它出错时会发生什么,因为这是我试图捕获/断言/记录的设置)我不知道是否在块中很重要。它所测试的只是分配给该代码运行的特定队列的一个键。正如我在这里所展示的,我将其用于一个函数,该函数通过同步地将块分配给队列或直接运行代码(如果已经在t上)来保证在特定队列上同步执行代码hat队列。dispatch\u get\u current\u queue()
被弃用,因为API的设计有缺陷,而不是实现有缺陷。您使用的预期替换功能确实是dispatch\u get\u specific()
@BradLarson如果你把它作为一个答案,我会把它标记为正确的。SimpleMan的答案很好,但我认为它更多的是一种变通方法,而不是直接的解决方案。