与Realm结合执行异步串行请求时遇到的问题 [英] Problems with performing asynchronous serial requests in combination with Realm

查看:86
本文介绍了与Realm结合执行异步串行请求时遇到的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想结合Realm执行一组串行异步请求.

I would like to perform a set of serial asynchronous requests in combination with Realm.

我要处理的请求集用于更新远程服务器,并由包含对象类型和本地uuid的结构数组确定.从Realm数据库中获取相关对象,然后使用Alamofire将其写入服务器.

The set of requests I want to process are used to update a remote server and are determined from an array of structs containing the object type and local uuid. The related objects are fetched from a Realm database and subsequently written to the server using Alamofire.

但是,获取Realm对象会导致错误(Realm accessed from incorrect thread).

However, fetching the Realm objects result in an error (Realm accessed from incorrect thread).

func performAsyncRequest<T: Object>(objectType: T.Type, uuid: String, failure fail: (()->Void)? = nil, success succeed: @escaping () -> Void)->Void {

    let realm = try! Realm() 
    let dataObject = realm.objects(objectType).filter("uuid == %@", uuid).first!
    let parameters = self.toJson(item: dataObject)

    // ** The Realm error occurs when the Alamofire request is performed  **

    let urlRequest = self.getRequest(objectType: T.self, with: parameters) 
    self.alamoFireManager.request(urlRequest) // Perform POST request
        .responseString { response in
            if let status = response.response?.statusCode {
                if status >= 200 && status <= 299 {
                    succeed() // Is not reached in combination with DispatchSemaphore
                } else if status >= 400 && status <= 499 {
                    fail?() // Is not reached in combination with DispatchSemaphore
                }
            }
    }
}

编辑:在下面的答案之后(解决了以前的Alamofire串行请求问题),对以下代码进行了编辑.

Edit: The code below is edited after the answer below (where a previous problem with the serial Alamofire request is solved).

为了顺序执行Alamofire请求,将OperationQueueDispatchSemaphore结合使用.

In order to perform the Alamofire requests serially, OperationQueue is used in combination with DispatchSemaphore.

    let operationQueue = OperationQueue()
    var operation: Operation!

    for requestData in requests { // requestData is a struct with the object Type and a uuid
        switch requestData.objectType {
            case is Object1.Type:
                operation = BlockOperation(block: {
                    let semaphore = DispatchSemaphore(value: 0)
                    self.performAsyncRequest(objectType: Object1.self, uuid: requestData.uuid, failure: { error in
                           semaphore.signal()
                       }) {
                       semaphore.signal()
                    }
                    semaphore.wait()
                })
            case is Object2.Type:
                    // ... same as for Object1 but now for Object2

            // .. and so on for other Objects                
            }
        operationQueue.addOperation(operation)
    }

如以下答案所示,由于Realm受线程限制,因此会发生错误.但是,我不清楚为什么Realm实例会跨不同的线程传递.

As indicated in the answer below the error occurs because Realm is thread confined. However, it is unclear to me why Realm instances are passed across different threads.

使用异常断点,我确定该错误发生在线程Queue: NSOperationQueue 0x… (QOS: UTILITY) (serial)上.这与执行BlockOperation的线程不同(因此,获取Realm对象的线程也不同).为什么BlockOperation中的方法不能在与NSOperationQueue相同的线程上执行?

With an exception breakpoint I determined that the error occurs on thread Queue: NSOperationQueue 0x… (QOS: UTILITY) (serial). This is a different thread from where BlockOperation is performed (and thus where the Realm objects are fetched). Why are the methods inside BlockOperation not performed on the same thread as NSOperationQueue?

任何解决这些问题的想法,我将不胜感激.

I would appreciate any ideas to handle these problems.

推荐答案

Realm和Realm对象是线程限制.您应该在每个线程上检索新的领域实例.不要跨其他线程传递Realm实例.

Realm and Realm objects are thread confinement. You should retrieve new realm instances on each thread. Do not pass a Realm instance across other threads.

似乎主线程由于等待信号量而停止.然后在主线程上执行Alamofire回调.因此,永远不会调用semaphore.signal(),因为主线程停止了. Alamofire的response*方法可以指定queue调用回调.

It seems the main thread stops due to waiting for the semaphore. Then Alamofire callbacks are executed on the main thread. So semaphore.signal() is never called because the main thread stops. Alamofire's response* methods can specify queue a callback is called.

这篇关于与Realm结合执行异步串行请求时遇到的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆