假设我们有多个线程发出打印件。 通常在下载内容时如下:
let url = self.url
print("loadPreview(\(source) for \(url)): ↝start loading \(self.url")
let task = session.downloadTask(with: url) {
(localUrl, response, error) in
print("loadPreview(\(source) for \(url)): == \(self.url")
}
有没有办法让print原子并阻止输出如下?
loadPreview(WSJ for www.wsj.co⟷TloadPreview(9loadPreview(appleins for appleinsid⟷n-messages): ↝start loading http://app⟷n-messages
答案 0 :(得分:1)
快速破解就是在打印件周围使用NSLock
。例如,您可以将原子打印函数定义为:
private let printLock = NSLock()
func aprint(_ message: String){
printLock.lock()
defer { printLock.unlock() }
print(message)
}
并像标准print
函数一样使用它:
aprint(“This will print atomically!”)
您还可以使用序列DispatchQueue
序列化打印调用来获得类似的结果。例如:
private let printQueue = DispatchQueue(label: "aprint", qos: .utility)
func aprint(_ message: String){
printQueue.async {
print(message)
}
}
此解决方案提供了更好的性能,主要归功于async
调用。这可确保调用线程不阻塞,直到获取锁定(并且完全执行相应的print
)。但是,很明显,这个解决方案也是完全原子的。
(对于记录,如果调用代码也在主队列上运行,那么简单地使用DispatchQueue.main
可能会表现得很奇怪。)
我建议选择第二种解决方案;)
答案 1 :(得分:0)
您可以使用DispatchIO
以非阻塞方式将输出自动序列化为stdout或文件。还有更多工作,您可能需要将以下示例包装到一个类中:
import Foundation
// Open stdout with DispatchIO
let queue = DispatchQueue.global()
let fd = FileHandle.standardOutput.fileDescriptor
let writer = DispatchIO(type: .stream, fileDescriptor: fd, queue: queue) { (errno) in
if errno != 0 {
print("Cannot open stdout: \(errno)")
}
}
// Encode string
if let data = string.data(using: .utf8) {
data.withUnsafeBytes { (buffer) in
// Produce DispatchData with encoded string
let dispatchData = DispatchData(bytes: buffer)
// Print string to stdout
writer.write(offset: .zero, data: dispatchData, queue: queue) { (done, data, errno) in
if errno != 0 {
print("Write error: \(errno)")
}
}
}
}
// Close the DispatchIO when you don't need it anymore
writer.close()