如何确保在同一后台线程上运行某些代码? [英] How to ensure to run some code on same background thread?

查看:80
本文介绍了如何确保在同一后台线程上运行某些代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的iOS Swift项目中使用领域.搜索涉及用于大数据集的复杂过滤器.因此,我正在后台线程上获取记录.

I am using realm in my iOS Swift project. Search involve complex filters for a big data set. So I am fetching records on background thread.

但是领域只能在创建领域的同一线程中使用. 我正在保存在后台线程上搜索Realm之后获得的结果参考.只能从同一后线程访问该对象

But realm can be used only from same thread on which Realm was created. I am saving a reference of results which I got after searching Realm on background thread. This object can only be access from same back thread

如何确保在不同时间将代码分派到同一线程?

How can I ensure to dispatch code at different time to the same thread?

我按照建议尝试了以下方法来解决此问题,但没有成功

I tried below as suggested to solve the issue, but it didn't worked

let realmQueue = DispatchQueue(label: "realm")
    var orginalThread:Thread?

    override func viewDidLoad() {
        super.viewDidLoad()

        realmQueue.async {
            self.orginalThread = Thread.current
        }

        let deadlineTime = DispatchTime.now() + .seconds(2)
        DispatchQueue.main.asyncAfter(deadline: deadlineTime) {
            self.realmQueue.async {
                print("realm queue after some time")

                if self.orginalThread == Thread.current {
                    print("same thread")
                }else {
                    print("other thread")
                }
            }
        }
    }

输出为

realm queue after some time

other thread

推荐答案

这是一个小型工作程序类,其工作方式与串行队列上的异步调度类似,可以保证所有工作项的线程均保持不变

Here's a small worker class that can works in a similar fashion to async dispatching on a serial queue, with the guarantee that the thread stays the same for all work items.

// Performs submitted work items on a dedicated thread
class Worker {

    // the worker thread
    private var thread: Thread?

    // used to put the worker thread in the sleep mode, so in won't consume
    // CPU while the queue is empty
    private let semaphore = DispatchSemaphore(value: 0)

    // using a lock to avoid race conditions if the worker and the enqueuer threads
    // try to update the queue at the same time
    private let lock = NSRecursiveLock()

    // and finally, the glorious queue, where all submitted blocks end up, and from
    // where the worker thread consumes them
    private var queue = [() -> Void]()

    // enqueues the given block; the worker thread will execute it as soon as possible
    public func enqueue(_ block: @escaping () -> Void) {
        // add the block to the queue, in a thread safe manner
        locked { queue.append(block) }

        // signal the semaphore, this will wake up the sleeping beauty
        semaphore.signal()

        // if this is the first time we enqueue a block, detach the thread
        // this makes the class lazy - it doesn't dispatch a new thread until the first
        // work item arrives
        if thread == nil {
            thread = Thread(block: work)
            thread?.start()
        }
    }

    // the method that gets passed to the thread
    private func work() {
        // just an infinite sequence of sleeps while the queue is empty
        // and block executions if the queue has items
        while true {
            // let's sleep until we get signalled that items are available
            semaphore.wait()

            // extract the first block in a thread safe manner, execute it
            // if we get here we know for sure that the queue has at least one element
            // as the semaphore gets signalled only when an item arrives
            let block = locked { queue.removeFirst() }
            block()
        }
    }

    // synchronously executes the given block in a thread-safe manner
    // returns the same value as the block
    private func locked<T>(do block: () -> T) -> T {
        lock.lock(); defer { lock.unlock() }
        return block()
    }
}

只需实例化它,然后让它完成工作即可:

Just instantiate it and let it do the job:

let worker = Worker()
worker.enqueue { print("On background thread, yay") }

这篇关于如何确保在同一后台线程上运行某些代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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