Tag: 并发

为什么我应该为每个新线程或NSOperation创build一个NSManagedObjectContext,而不是在主线程上调用Core Data?

一些开发人员已经告诉我,我可以为每个新线程创build一个新的NSManagedObjectContext实例,以使Core Data线程安全。 那么我只好照顾之后的合并。 对我来说,这听起来像是很多额外的代码和开销。 是否有这个解决scheme不好的原因? 它来了: 而不是为每个新线程或每个NSOperation创build一个新的MOC,我将在主线程上执行MOC-更改,就像我们从UIKit知道的一样。 我只是调用-performSelectorOnMainThread:…waitUntilDone:YES并摆脱所有的核心数据并发问题。 优点: – 不必为每个Thread / NSOperation创build一个新的MOC。 – 不必将MOC合并在一起。 – 确保没有并发问题,因为核心数据保持在主线程安全的地方。 缺点: – 调用像-performSelectorOnMainThread:…waitUntilDone:YES看起来丑陋,难以阅读。 – 线程/ NSOperation被阻止。 但实际上,系统无论如何不能一次做多件事情。 就我而言,核心数据部分不是性能瓶颈。 围绕它的繁重计算是在后台线程或NSOperation中进行的。 你怎么看? 这值得探索吗? 为什么你仍然喜欢为每个新的线程/ NSOperation创build一个MOC,然后处理合并? 相比于在主线程上做这个,这有什么好处呢?

将子项ManagedObjectContext所做的更改复制到实体的父级

我期望(甚至希望)这将是一个愚蠢的问题,但经过这个问题摔跤了好几个小时,我需要一些见解。 我的iOS 5.1应用程序使用嵌套的MOC(具有PrivateQueueConcurrency子MOC),将其称为MOC-Child,其父母是MainQueueConcurrency MOC,将其称为MOC-Parent。 MOC-Parent支持显示其实体的表视图。 MOC-Child被parsing器使用,该parsing器在非主线程上asynchronous运行,以创build与从URL连接parsing的XML实体描述对应的新实体,然后将新实体推送到MOC-Parent,通过保存在MOC-Child上,以表格forms显示它们。 这很好用: 1) Parser creates entity in MOC-Child 2) Parser saves MOC-Child 3) New entity is added to MOC-Parent 4) New entity is displayed in MOC-Parent's table view 但是,此提要中任何给定实体的描述可能会随时间而改变,以便它所描述的实体需要在应用中进行修改,并更新表视图中的单元格。 因此,对于Feed中的每个实体描述,parsing器都会尝试获取MOC-Child中与所描述的实体具有相同ID的实体(如果有的话),如果有人将现有实体的值与描述值进行比较,看看是否有任何改变。 当parsing器以这种方式检测到实体已被修改时,它用MOC-Child中的新值更新MOC-Child中现有实体的值,然后保存MOC-Child以将更改推送到MOC-Parent。 这是事情出错的地方。 我曾经想过,对MOC-Child中的获取实体所做的更改,如果通过保存而被推送给父项,则会简单地“出现”到MOC-Parent中的“相同”实体中。 但是,我所看到的情况是,将来自MOC-Child的已更改的实体添加到MOC-Parent, 好像它是一个完全独立的新实体 ; 结果是MOC-Parent以及它驱动的表视图对于每个被修改的实体最终有两个实体: 1) Parser modifies existing entity in MOC-Child 2) Parser saves MOC-Child 3) Modified […]

快速替代互斥

我有多个线程之间的共享内存。 我想阻止这些线程同时访问这块内存。 (如生产者 – 消费者问题) 问题 : 一个线程将元素添加到队列中,另一个线程读取这些元素并将其删除。 他们不应该同时访问队列。 解决这个问题的一个办法是使用Mutex。 正如我所发现的,Swift中没有互斥体。 Swift中有没有其他的select?

在iOS 7上使用Private Queue Deadlocks Parent的子级上下文执行块locking和等待

我有两个名为importContext和childContext NSManagedObjectContext 。 childContext是childContext的子importContext ,它们都是NSPrivateQueueConcurrencyType 。 为了避免主线程,我在importContext的队列上做了一堆工作。 这个工作涉及到大量的提取和保存,所以将整个事件封装到importContext的performBlockAndWait:中是很importContext (因为在performBlockAndWait之后的代码依赖于它的结果, 所以需要通过同步操作)。 在这个工作的某个时候,我可能需要从JSON结果创build新的托pipe对象。 这些JSON值可能是无效的,并且我的validation失败,所以在创build对象之后,如果它们不好,我需要将它们排除。 这是childContext进来的地方。我插入我的新对象,如果它的JSON属性最终没有意义,我抛弃了childContext 。 问题来了,当我需要保存childContext 。 我期望它有自己的私人队列,从其父队列分开。 但是,这只会导致iOS 7(不是iOS 8)上的死锁。 当我在iOS 8模拟器和设备上运行相同的代码时, childContext会在单独的线程上创build自己的队列并正确保存。 看起来好像当我运行iOS 7时, childContext试图save:在父队列中,但是父母正在等待其导致死锁的孩子。 在iOS 8中,这不会发生。 有谁知道为什么? 这是简化的代码: -(NSManagedObjectContext *)importContext { NSManagedObjectContext* moc = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; moc.persistentStoreCoordinator = [self storeCoordinator]; return moc; } -(void)updateItems:(NSArray*)ItemDescriptions { [self.importContext performBlockAndWait:^{ //get info and update … […]

Swift 3 GCDlockingvariables和block_and_release错误

我正在使用Swift 3 GCD来执行我的代码中的一些操作。 但是我经常遇到_dispatch_call_block_and_release错误。 我想这个错误背后的原因是因为不同的线程修改相同的variables,但我不知道如何解决问题。 这是我的代码和解释: 我有一个variables在不同的线程中被访问和修改: var queueMsgSent: Dictionary<Date,BTCommand>? = nil func lock(obj: AnyObject, blk:() -> ()) { objc_sync_enter(obj) blk() objc_sync_exit(obj) } func addMsgSentToQueue(msg: BTCommands) { if queueMsgSent == nil { queueMsgSent = Dictionary.init() } let currentDate = Date() lock(obj: queueMsgSent as AnyObject) { queueMsgSent?.updateValue(msg, forKey: currentDate) } } func deleteMsgSentWithId(id: Int) { if […]

在当前队列上同步分派

我知道你可能会发现这是一个奇怪的问题,但我只是学习GCD,我想完全理解它的所有方面。 所以这里是: 是否有任何理由在CURRENT QUEUE上派发任务SYNC? 例如: dispatch_queue_t concurrentQueue = dispatch_get_global_queue(…); dispatch_async(concurrentQueue, ^{ //this is work task 0 //first do something here, then suddenly: dispatch_sync(concurrentQueue, ^{ //work task 1 }); //continue work task 0 }); 我明白了一件事情:如果不是concurrentQueue而是使用一个串行队列,那么我会在该串行队列上发生死锁,因为work task 1在work task 0完成之前不能启动(因为保证执行顺序的串行队列) ,同时work task 0不能继续执行,因为它等待SYNC dispath函数返回(如果我错了,请纠正我,这将使我总是noob)。 所以回到原来的想法,上面的代码和相同的代码之间有什么区别,而不是调用dispatch_sync函数,我直接写work task 1代码?

CoreDataasynchronous获取导致并发debugging器错误

我正在使用 -com.apple.CoreData.ConcurrencyDebug 启动时debugging我的CoreData应用程序中的并发性。 在应用程序启动期间,我对主线程的托pipe对象上下文执行asynchronous获取。 // set up the async request NSError * error = nil; [MOC executeRequest:asyncFetch error:&error]; if (error) { NSLog(@"Unable to execute fetch request."); NSLog(@"%@, %@", error, error.localizedDescription); } 这个代码是从主线程调用的,但是executeRequest:将它排入另一个线程,我知道这是正确的行为。 并发debugging器不喜欢这个,说(我认为)我在这里做错了什么。 我也试过在[MOC performBlock:]包装这也是[MOC performBlock:] ,但也会导致multithreading违规。 在这两种情况下,我得到这个: [NSManagedObjectContext __Multithreading_Violation_AllThatIsLeftToUsIsHonor__ 我是使用asynchronous提取不正确,还是在这里的并发debugging器错误? 编辑:我也试图包装它在MOC performBlock应该确保它从主线程调用。 在任何情况下,调用都从主线程中排队 ,但在其他地方执行。 编辑:这里是获取请求: NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"MyEntity"]; NSPredicate * pred […]

iOS核心数据何时保存上下文?

由于并发性和multithreading,我的核心数据随机崩溃。 我知道核心数据不是线程安全的。 我还发现了一些关于如何创buildThreadedDataService并为每个线程实例化单独的上下文的其他答案。 这一点对于我来说现在有点太多了,所以我试图find一个更简单的方法。 我现在正在尝试的解决scheme很简单: 通过主线程保存数据。 但是,现在出现了一个新的问题: 僵局 。 该应用程序变得没有响应,因为我的每个插入一个新的NSManagedObject紧跟着一个调用来保存。 (这是我最好的猜测)。 阅读App Delegate文档,我发现它build议我在applicationWillTerminate中保存上下文。 我的问题是这样的: 对于每分钟插入一个新事件的长时间运行的操作,并且用户不需要立即看到传播到所有控制器的更新,什么时候是我保存上下文的好时机? 我觉得每个logging的保存环境可能是一个矫枉过正的感觉? -(void)insertNewEvent { // Create a new instance of the entity managed by the fetched results controller. NSManagedObjectContext *context = [self.fetchedResultsController.managedObjectContext]; NSEntityDescription *entity = [[self.fetchedResultsControllerfetchRequest] entity]; Event*newManagedObject = (Event*)[NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context]; //use accessor methods to set default values // […]

NSOperationQueue mainQueue vs performSelectorOnMainThread?

这有什么区别: [[NSOperationQueue mainQueue] addOperationWithBlock:^{ [self doSomthing:object]; }]; 和这个: [self performSelectorOnMainThread:@selector(doSomething:) withObject:object waitUntilDone:NO]

iOS GCD:任何全局队列和具有后台优先级(DISPATCH_QUEUE_PRIORITY_BACKGROUND)之间的区别?

我正在阅读并发编程指南和东西混淆了我。 我看到很多代码调用以下任何后台任务: dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 现在我所说的“背景”是stream行的意思: 除了主(UI)线程之外的任何地方执行的东西 因此,在文档之后,上面的语句返回具有不同优先级的任何非主线程队列。 我的问题是 – 为什么然后DISPATCH_QUEUE_PRIORITY_BACKGROUND存在? 最近我还看到许多使用DISPATCH_QUEUE_PRIORITY_BACKGROUNDasynchronous任务来执行后台任务。 DISPATCH_QUEUE_PRIORITY_DEFAULT , DISPATCH_QUEUE_PRIORITY_LOW或DISPATCH_QUEUE_PRIORITY_HIGH返回的队列是否与主线程相距甚远,如果使用dispatch_get_global_queue返回? 他们不是背景排队吗? 用DISPATCH_QUEUE_PRIORITY_BACKGROUND返回的队列有什么具体的用途? 我已经提到了这个,但是除了上面提到的stream行的含义之外,它没有多less澄清。 我相信我很迷茫的话 – 背景和背景排队。 如果有人可以解释(更好,graphics) – 将是一个很大的帮助。