Multithreading Swift:如何将工作线程放到单独的线程中,在主视图中显示结果?
我想知道是否有一种简单的方法可以做到这一点:将一个长期运行的worker放在一个单独的线程中,这样就不会阻塞UI。并在主视图中显示结果。在SwiftUI或UIKit下。我在网上发现的一切都非常复杂。或者在Swift中是否有完全不同的方法 我制作了一个简约的Python程序来展示我想要做什么。它以MacOS显示WiFi信号强度Multithreading Swift:如何将工作线程放到单独的线程中,在主视图中显示结果?,multithreading,swiftui,uikit,worker,long-running-processes,Multithreading,Swiftui,Uikit,Worker,Long Running Processes,我想知道是否有一种简单的方法可以做到这一点:将一个长期运行的worker放在一个单独的线程中,这样就不会阻塞UI。并在主视图中显示结果。在SwiftUI或UIKit下。我在网上发现的一切都非常复杂。或者在Swift中是否有完全不同的方法 我制作了一个简约的Python程序来展示我想要做什么。它以MacOS显示WiFi信号强度 import time import sys import subprocess from PyQt5.QtWidgets import QApplication, QWi
import time
import sys
import subprocess
from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QHBoxLayout
from PyQt5.QtCore import QObject, pyqtSignal, QThread
class Worker(QObject):
send_output = pyqtSignal(str)
def __init__(self):
super().__init__()
def worker(self):
while True:
_out = subprocess.check_output(
["/System/Library/PrivateFrameworks/Apple80211.framework/Versions/Current/Resources/airport",
"-I"])\
.decode("utf-8")
self.send_output.emit("RSSI: " + _out.splitlines()[0][-3:] + " dBm")
time.sleep(2)
class MainWindow(QWidget):
do_work = pyqtSignal(object)
def __init__(self):
super().__init__()
self.label = QLabel()
layout = QHBoxLayout()
self.setLayout(layout)
layout.addWidget(self.label)
self.show()
self.app_thread = QThread()
self.app = Worker()
self.app.moveToThread(self.app_thread)
self.app.send_output.connect(self.output_label)
self.app_thread.started.connect(self.app.worker)
self.app_thread.start()
def output_label(self, _str):
self.label.setText(_str)
if __name__ == '__main__':
application = QApplication(sys.argv)
mainwindow = MainWindow()
sys.exit(application.exec())
我现在正想办法进入斯威夫特。这很令人兴奋,但确实是件大事。提前谢谢 这是一个非常宽泛的问题,所以我也将回答相当宽泛的问题 是的,您可以在单独的线程中运行任务,然后将数据返回到主线程。有很多方法可以做到这一点,常见的方法是
DispatchQueue
让我们举一个过于简化的例子(绝对不是指真实世界的代码):
在本例中,当视图出现时,任务通过DispatchQueue
在后台线程中运行。在本例中,我只是利用了这样一个事实:如果打印到控制台上一百万次,那么这是一个相当昂贵的操作
完成后,它将发回主线程并更新状态变量中的结果
DispatchQueue
不是特定于UIKit或SwiftUI的——使用SwiftUI将演示放在一起最简单
如果您真的要开始编写代码来实现这一点,您可能希望对DispatchQueues如何工作进行一些研究,包括使用哪个队列、是否创建自己的队列、是否希望按顺序完成任务等,但出于这样一个广泛问题的目的,即这是否可以完成(以及如何容易完成),这至少说明了基本情况。非常感谢您的快速回复。是的,我一定会进入DispatchQueue docu。是的,打印效果很好。这不是问题所在。但对于我的情况:我想在worker中的每次迭代之后更新UI视图。在辅助进程完成后不会进行。没问题——在循环/任务中调用DispatchQueue.main.async{}。是的,在此期间我自己也尝试过。非常有效。这就是我想要的!!!我很高兴。现在,对我来说,深入了解如何和为什么等是有意义的。我真的很喜欢Swift的概念。特别是在数据类型安全方面。但这确实是一个巨大的问题,很难从哪里开始。但你告诉了我重点。非常感谢你!!
struct ContentView : View {
@State var result = ""
var body: some View {
Text("Result: \(result)")
.onAppear {
DispatchQueue.global(qos: .background).async {
//do your long-running code
var innerResult = 0
for i in 0...1000000 {
innerResult += 5
print(i)
//use DispatchQueue.main.async here if you want to update during the task
}
//update at the end:
DispatchQueue.main.async {
result = "Done! \(innerResult)"
}
}
}
}
}