如何确保在同一后台线程上运行某些代码? [英] How to ensure to run some code on same background thread?
问题描述
我在我的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屋!