• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

objective-c - 获取例程中的死锁

[复制链接]
菜鸟教程小白 发表于 2022-12-12 19:52:51 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我坚持使用我的第一个 GCD 和第一个核心数据,使用应用程序 =)

两个 View 访问相同的数据(由单个 DAO 处理)。

如果我等待当前 View 完成加载其内容,则在更改 View 时不会出现问题。

但是:如果我在一个 Controller 尝试从我的模型中获取数据时更改 View (其基于选项卡的 View ),则新 Controller 会尝试相同的操作,并且线程“冲突”并且我的应用程序会卡住。

卡住发生在我的 DAO 的这行代码中:

    NSArray *results = [managedObjectContext executeFetchRequest:fetch error:&error];    

reloadAllMonth() 访问我的 DAO 的 fetch 例程

我如何在第一个 Controller 中加载数据:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
                [self reloadAllMonth];

                dispatch_async(dispatch_get_main_queue(), ^(void) {                        
                    [self.allMonthTable reloadData];    
                });

在第二个 View Controller 中,我做的第一件事是更新我的 DAO,这当然使用(在其他人之下)我之前调用的完全相同的 fetch 例程:

    [self.dataHandler updateData];

到目前为止,我已经尝试了两种方法:

首先使用 c 信号量:

-(NSArray *)fetchAllMonthExpenses{  
    //@return: array of all expenses in month (day & month type)


    NSNumber *monthNumber = [self getMonthNumber:[NSDate date]];
        NSEntityDescription *exp = [NSEntityDescription entityForName"Expense" inManagedObjectContext:managedObjectContext];
    NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
    [fetch setEntity:exp];
    [fetch setPredicate:[NSPredicate predicateWithFormat"month == %@",monthNumber]];
    NSError *error = nil;
    sem_wait(&isLoading);
    NSArray *results = [self.managedObjectContext executeFetchRequest:fetch error:&error];  
    sem_post(&isLoading);
    return results;

}

使用同步指令

-(NSArray *)fetchAllMonthExpenses{  
    //@return: array of all expenses in month (day & month type)


    NSNumber *monthNumber = [self getMonthNumber:[NSDate date]];
        NSEntityDescription *exp = [NSEntityDescription entityForName"Expense" inManagedObjectContext:managedObjectContext];
    NSFetchRequest *fetch = [[NSFetchRequest alloc]init];
    [fetch setEntity:exp];
    [fetch setPredicate:[NSPredicate predicateWithFormat"month == %@",monthNumber]];
    NSError *error = nil;
    @synchronized(self.class){
        NSArray *results = [self.managedObjectContext executeFetchRequest:fetch error:&error];  
        return results;
    }    
}

遗憾的是这两种方法都不起作用,应用程序卡住了我所做的一切。

所以我的问题是:我做错了什么(正如我第一次使用线程时提到的),我错过了什么,我应该去哪里看?

这已经让我忙了 2 天了,我似乎无法理解它:/



Best Answer-推荐答案


一个 NSManagedObjectContext 和其中的所有 NSManagedObjects 都不是线程安全的。

无论您使用什么线程来创建上下文,都需要是 only 线程,您可以在其中执行与该上下文相关的任何事情。即使只是从一个托管对象中读取值也必须在该线程上完成,而不是在任何其他线程上完成。

如果您需要两个线程同时处理同一个数据库,您有两种选择:

  • 使用 dispatch_sync() 暂时跳转到另一个线程以对托管对象和/或上下文执行所有读/写操作

或者:

  • 在另一个线程中为同一个数据库创建第二个 NSManagedObjectContext,并使对这两个上下文所做的任何更改保持同步。

第一个选项更容易,但可能会消除线程的大部分好处。第二个选项更难,但可以做到,并且有一个相当不错的 API 可以使不同线程上的两个上下文保持同步。

查看核心数据编程指南了解更多详情。

关于objective-c - 获取例程中的死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9889475/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap