Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
183 views
in Technique[技术] by (71.8m points)

ios - How to ensure to run some code on same background thread?

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.

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")
                }
            }
        }
    }

Output is

realm queue after some time

other thread
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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") }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...