如何确保在同一背景线程上运行一些代码



我在iOS Swift项目中使用领域。搜索涉及大数据集的复杂过滤器。所以我在背景线程上获取记录。

,但领域只能从创建领域的同一线程中使用。我正在保留在背景线程上搜索领域后获得的结果的参考。此对象只能从同一背线访问

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

我在下面建议解决该问题,但它没有起作用

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

这是一个小型工人类,可以与串行队列上的异步派遣类似的方式工作,并保证该线程在所有工作项目中保持不变。

// 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()
    }
}

只是实例化并让它完成工作:

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

您必须为此创建自己的线程。Apple给出了目标C中的自定义运行循环的示例。

class MyThread: Thread {
    public var runloop: RunLoop?
    public var done = false
    override func main() {
        runloop = RunLoop.current
        done = false
        repeat {
            let result = CFRunLoopRunInMode(.defaultMode, 10, true)
            if result == .stopped  {
                done = true
            }
        }
        while !done
    }
    func stop() {
        if let rl = runloop?.getCFRunLoop() {
            CFRunLoopStop(rl)
            runloop = nil
            done = true
        }
    }
}

现在您可以这样使用:

    let thread = MyThread()
    thread.start()
    sleep(1)
    thread.runloop?.perform {
        print("task")
    }
    thread.runloop?.perform {
        print("task 2")
    }
    thread.runloop?.perform {
        print("task 3")
    }

NOTE sleep不是很优雅而是需要,因为该线程需要一些时间才能进行启动。最好检查是否设置了属性runloop,并在必要时执行块。我的代码(尤其是runloop(可能在比赛条件下不安全,仅供演示。;-)

最新更新