核心数据线程和锁争用问题

2024-01-25

我目前正在编写 iOS 应用程序的同步引擎。我正在编写的方法之一是重新加载数据函数,其中应用程序重新下载用户的数据及其所有照片。这是一项昂贵的操作(时间方面),所以我创建了一个NSOperation子类,SSReloadDataOperation。它下载数据,获取 currentUser 实体,从该 currentUser 中删除所有现有照片,然后重新填充它。

然而,即使我认为这是线程安全的,有时在操作运行时并且-currentUser从其他地方访问时,应用程序崩溃,大概是在尝试获取它时。其他时候,UI 有时只是冻结,并且在调试器中暂停显示它总是停在某个位置-currentUser NSFetchRequest执行调用。

如何使此操作线程安全且原子,以便我可以下载并重新填充而不阻塞主 UI 线程,并且仍然有-currentUser可以访问吗?在使用锁或架构方面我缺少什么吗?谢谢你!

Code:

- (void)main
{
  // Download the photo data
  [[SyncEngine defaultEngine] getUserPhotosWithCompletionBlock:^(NSMutableArray *photos)
  {
     if (photos)
     {
         // Create a new NSManagedObjectContext for this operation

         SSAppDelegate* appDelegate = [[UIApplication sharedApplication] delegate];
         NSManagedObjectContext* localContext = [[NSManagedObjectContext alloc] init];
         [localContext setPersistentStoreCoordinator:[[appDelegate managedObjectContext] persistentStoreCoordinator]];

         NSNotificationCenter* notificationCenter = [NSNotificationCenter defaultCenter];
         [notificationCenter addObserver:self
                                selector:@selector(mergeChanges:)
                                    name:NSManagedObjectContextDidSaveNotification
                                  object:localContext];

         NSError* error;
         NSFetchRequest* request = [[[SyncEngine defaultEngine] managedObjectModel] fetchRequestFromTemplateWithName:@"CurrentUser" substitutionVariables:[[NSDictionary alloc] init]];
         User* currentUser = [[localContext executeFetchRequest:request error:&error] objectAtIndex:0];

         // Remove the old data
         [currentUser setPhotos:[[NSSet alloc] init]];

         // Iterate through photo data, repopulate
         for (Photo* photo in photos) {
             [currentUser addPhotosObject:photo];
         }

         if (! [localContext save:&error]) {
             NSLog(@"Error saving: %@", error);
         }

         NSLog(@"Completed sync!");
     }
  } userId:[[[SyncEngine defaultEngine] currentUser] userId]];
}

-currentUser 便捷方法,通常从主线程调用。

- (User *)currentUser
{
   NSError* error;
   NSFetchRequest* request = [self.managedObjectModel fetchRequestFromTemplateWithName:@"CurrentUser" substitutionVariables:[[NSDictionary alloc] init]];
    NSArray* result = [self.managedObjectContext executeFetchRequest:request error:&error];
    if ([result count] == 1) {
    return [result objectAtIndex:0];
    }
    return nil;
}

你是对的,这种冻结感觉像是线程问题。

因为托管对象必须在使用其上下文和创建它们的同一线程或串行队列中使用,所以不可能有像这样的方法currentUser从示例中,让它神奇地返回线程安全的托管对象。

但您可以将上下文作为参数传递。调用者将决定在哪种上下文中复活用户。

- (User *)userWithContext:(NSManagedContext *)context {
    User *user = nil;

    NSError *error;
    NSFetchRequest *request = ...;
    NSArray *userArray = [context executeFetchRequest:request error:&error];
    if (userArray == nil) {
        NSLog(@“Error fetching user: %@“, error);
    } else if ([userArray count] > 0) {
        user = userArray[0];
    }

    return user;
}

这是关于您的代码片段的其他想法。

您在操作的主上下文中创建的上下文可以是主上下文的子上下文。然后,保存该子项后,保存父项(如果您希望此时将数据存储到存储中)。使用父子关系时,您不需要订阅 did-save 通知并合并其中的更改。

从技术上讲,您无法从操作的 main 访问主上下文的持久存储协调器。因为它只允许与来自一个线程或队列的上下文一起工作(调用任何方法)。我打赌你在主线程上创建了你的主要上下文。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

核心数据线程和锁争用问题 的相关文章

随机推荐

  • 如何在单引号中使用 bash 变量

    我的 bash 代码如下 payload text failure with VAR failed for 但变量未解析为实际值 请不要给出否定 因为我在 Bash 方面没有太多经验 变量不会在单引号中扩展 这意味着您只需确保它们不是单引号
  • MKMapView 完全缩小时的缩放问题

    我通过单击按钮缩小地图 因此 当地图完全缩小时 如果我尝试再次缩小它 那么它在设置区域时会崩溃 不确定 但是有什么方法可以检测地图是否达到最大缩放限制吗 这是我缩小地图的代码 void setZoomLevelForNoPicksCurre
  • AJAX、PHP 会话和同时请求[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我就直接进入正题吧 当用户提交搜索时
  • 我在 env 渲染中遇到错误 - env.render()

    我试图在渲染时实现 Atari Games 但出现如下错误 line 283 in render raise error Error gym error Error render mode human is deprecated Pleas
  • 网络表单中的构造函数?

    我有一个 ASP NET Web 表单 我在其中初始化一个数组 其中包含页面上的控件列表 如下所示 FileUpload 4 new FileUpload 4 public myclass fileUpload 0 FileUpload1
  • PyCharm 中“没有名为管理的模块”

    我在使用 PyCharm 时遇到问题 当我单击 工具 中的 运行 Django 控制台 或 运行管理 py 任务 时 我得到 Traceback most recent call last File
  • 为iPhone 5创建opencv相机矩阵solvepnp

    我正在使用 opencv 为 iPhone 开发一个应用程序 我必须使用方法solvePnPRansac http opencv willowgarage com documentation cpp camera calibration a
  • 即使使用动态高度网站,如何将页脚保持在底部

    当我有一个使用 CSS 动态设置高度 例如从数据库获取信息 的页面时 如何将页脚 div 始终保持在窗口底部 如果你想使用 jQuery 我想出了这个并且工作得很好 设置页脚的 CSS footer position absolute wi
  • 将 props 传递到 React 组件

    我刚刚开始学习 React 正在创建组件并将 props 传递给它们 我是否必须在下面的示例中引用 JSX 元素中的 props 我已经看到过引用 props 和未引用 props 的示例 并且这两个选项似乎都有效 const name J
  • 如何获得可靠的 Cortex M4 短延迟

    我正在将一些代码从 M3 移植到 M4 它使用 3 个 NOP 在串行输出时钟更改之间提供非常短的延迟 M3指令集将NOP的时间定义为1个周期 我注意到 M4 中的 NOP 并不一定会延迟任何时间 我知道我需要禁用编译器优化 但我正在寻找一
  • 如何使用 Handlebars.js 将字段小写?

    我想做这样的事情 user name toLowerCase 但我收到此错误 Error Parse error on line X tatus user name toLowerCase gt Expecting ID got undef
  • 如何使输入可观察?

    我有一个带有一些输入的组件 我希望在它发生更改时收到通知 我目前通过实施来使其工作ngOnChanges并找出哪个输入被更改 但是 我更愿意将输入声明设置为 Input select values selectValues Observab
  • For 循环范围必须有一个“iterator()”方法

    我遇到了这个奇怪的错误 val limit Int applicationContext resources getInteger R integer popupPlayerAnimationTime for i in limit 我找到了
  • 如何以编程方式添加多列 ListViewItem 而无需任何数据绑定?

    我有一个带有 3 个标头的 ListView 在 XAML 中声明如下
  • Mono 运行时的局限性

    我的问题类似于this one https stackoverflow com questions 802559 limitations in mono for a net framework developer and this one
  • 将 Chart JS 2 上的条形图扩展为新型图表

    我实际上正在使用 Chart JS 2 0 1 在页面上绘制图表 我的客户要求我在条形图中添加一条线 以便他们可以看到他们不能超过的限制 像那样 y 轴上有线条的条形图 https i stack imgur com 5XJO4 png 因
  • 使用 Apache POI 合并 Excel 中的单元格

    还有其他方法可以使用 Apache POI 库合并 Excel 中的单元格吗 我正在尝试使用以下内容 但它不起作用 selecting the region in Worksheet for merging data CellRangeAd
  • Boost Hana :将 Hana 类型转换为 std::string

    是否存在用于编译时转换 a 成员类型的 Boost Hana 方法Struct类型名的 std string 的 STL 容器的概念 例如 MyType t std array
  • Vala:陷阱、提示和技巧

    作为一名刚接触 Vala 的程序员 您对刚接触该语言的人的第一条建议是什么 这很大程度上取决于您来自什么背景 如果您来自 C C Java 最好的建议是学习函数式编程 Vala 支持真正的闭包 因此您应该 深入 学习如何使用 lambda
  • 核心数据线程和锁争用问题

    我目前正在编写 iOS 应用程序的同步引擎 我正在编写的方法之一是重新加载数据函数 其中应用程序重新下载用户的数据及其所有照片 这是一项昂贵的操作 时间方面 所以我创建了一个NSOperation子类 SSReloadDataOperati