【问题标题】:Realm Threading Confusion领域线程混乱
【发布时间】:2015-12-09 18:28:38
【问题描述】:

所以我正在努力设置一个后台队列,该队列在其自己的线程上执行所有领域写入。我遇到了一些我无法弄清楚的奇怪问题。

问题 #1

我不确定这是否相关(见帖子:Xcode debug issues with realm),但我的lldbg 输出确实与某个字段是否存在明显不匹配: messages元素

我的数据类型

OTTO会话

class OTTOSession : Object {
  dynamic var messages : MessageList?
  dynamic var recordingStart  : Double = NSDate().timeIntervalSince1970

func addLocationMessage(msg : dmParsedMessage) -> LocationMessage {
    let dmsg : dmLocationMessage = msg as! dmLocationMessage
    let locMsg = LocationMessage(locMsg: dmsg)
    self.messages!.locationMessages.append(locMsg)
    return locMsg;
  }
}

消息列表

public class MessageList : Object     {

dynamic var date : NSDate = NSDate();
dynamic var test : String = "HI";
let locationMessages = List<LocationMessage>()
let ahrsMessages = List<AHRSMessage>()
//    let statusMessages = List<StatusMessageRLM>()
let logMessages = List<LogMessage>()
}

领域交互

在我的代码中,我在 realmQueue 的代码块中创建了新的 OTTOSession

internal var realmQueue = dispatch_queue_create("DataRecorder.realmQueue", 
                                                   DISPATCH_QUEUE_SERIAL)

所有领域调用都在此realmQueue 线程上完成

  dispatch_async(realmQueue) {
        self.session = OTTOSession()
    }

我也尝试过不同的变体,例如:

  dispatch_async(realmQueue) {
        self.session = OTTOSession()

        // Directly making a message list
        self.session!.messages = MessageList()

        //Making a separate message list var
        self.messages = MessageList()
        self.session!.messages = self.messages
    }

我使用 MessageList 的原因是我无法通过调试器判断 .messages 变量是否已设置

录音

一旦我向我的进程发出信号,我想开始录制,然后我实际上会向 Realm 发出写入调用(我不是 100% 确定我做得正确)

dispatch_async(realmQueue){

        // Update some of the data
        self.session!.recordingStart = NSDate().timeIntervalSince1970

        // Then start writing the objects
        try! Realm().write {

            // I've tried different variants of:
            let session = self.session!
            try! Realm().add(self.session!)                          
            // Or
            try! Realm().add(self.session!)

            // or            
            let session = self.session!                
            session.messages = MessageList()
            session.messages!.ahrsMessages
            try! Realm().add(self.session!)
            try! self.session!.messages = Realm().create(MessageList)
            try! Realm().add(self.session!.messages!)

            print ("Done")
        }
    }

基本上,我尝试了各种尝试将对象放入领域的组合。

问题:当添加具有one-to-one 关系的对象时,我是否必须将两个对象都添加到 Realm 中,或者仅添加 parent 对象会导致相关对象也添加到领域中

添加数据

当我开始向我的对象添加数据时,事情就开始出错了。

在我的 OTTOSession 对象中,我有以下功能:

func addLocationMessage(msg : dmParsedMessage) -> LocationMessage {
    let dmsg : dmLocationMessage = msg as! dmLocationMessage
    let locMsg = LocationMessage(locMsg: dmsg)

    // THIS LINE IS CAUSING A 'REALM ACCESSED FROM INCORRECT THREAD ERROR
    self.messages!.locationMessages.append(locMsg)

    return locMsg;
}

我在这一行遇到访问错误:

self.messages!.locationMessages.append(locMsg)

现在函数调用本身被包装在以下块中:

dispatch_async(realmQueue) {
    try! Realm().write {
        self.session?.addLocationMessage(msg)
   }
}

据我所知,通过查看调试器和查看代码 - 一切都应该在正确的线程中运行。

我的队列是SERIAL,所以事情应该一个接一个地发生。我唯一想不通的是,当我在这一点上中断时,调试器确实显示messagesnil,但我不能相信,因为:

问题

所以我的问题有两个

1) 我在 RealmDB 中添加对象的代码是否正确。即我是否需要为OTTOSessionMessageList 分别拨打两个Realm().add 电话,或者我可以只打一个电话吗

2) 有什么东西可以解释为什么我在这里遇到线程冲突 - 在一个线程上完成我所有的领域编写调用就足够了吗?

【问题讨论】:

  • 如果您下次可以将关注点分开并通过分开的问题单独解决它们会更好。这样更容易回答。
  • 解决您的LLDB问题:您是否同时安装了Realm插件?这样,两个窗格上的输出应该是同步的。如有疑问,您可以相信 po 的动态评估结果,因为它始终对 Realm 的内部有充分的了解。

标签: ios xcode multithreading swift realm


【解决方案1】:

1) 不,您不需要对Realm.add() 进行两次单独的调用。当您将对象添加到领域时,所有相关对象也会被持久化。

2) 您的线程违规很可能源于调度队列无法保证执行它们的线程(在主队列旁边)。这意味着您的 Realm 队列在不同的线程上执行。您需要确保从在此线程上打开的领域中检索您的会话对象。您可能希望为此目的使用主键并在队列/线程之间共享主键。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-22
    • 2017-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多