我在iOS Swift项目中使用领域。搜索涉及大数据集的复杂过滤器。所以我在后台线程上获取记录。
但是,realm只能在创建Realm的同一个线程中使用。 我正在保存在后台线程上搜索Realm后得到的结果的引用。该对象只能从相同的后台线程访问
如何确保在不同时间将代码分发到同一个线程?
我按照建议解决了这个问题,但是没有用
struct Pixel {
BYTE Blue;
BYTE Green;
BYTE Red;
BYTE Alpha;
};
输出
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")
}
}
}
}
答案 0 :(得分:7)
这是一个小型的工人类,它可以以与串行队列上的异步调度类似的方式工作,并保证所有工作项的线程保持不变。
// 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") }
答案 1 :(得分:3)
你必须创建一个带有运行循环的自己的线程。 Apple为a custom run loop in Objective C举了一个例子。您可以在Swift中创建一个类似的线程类:
@app.route("/upload", methods=['POST'])
def upload():
target = os.path.join(APP__ROOT, 'data/')
print(target)
if not os.path.isdir(target):
os.mkdir(target)
for file in request.files.getlist("file"):
filename = file.filename
print(filename)
destination = "/".join([target, filename])
print(destination)
file.save(destination)
return render_template("downloads.html")
现在您可以像这样使用它:
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")
}
不是很优雅但需要,因为线程需要一些时间才能启动。最好检查属性sleep
是否已设置,并在必要时稍后执行该块。我的代码(特别是runloop
)可能不适合竞争条件,而且仅用于演示。 ;-)