如何在swift中使用线程?
dispatchOnMainThread:^{
NSLog(@"Block Executed On %s", dispatch_queue_get_label(dispatch_get_current_queue()));
}];
Run Code Online (Sandbox Code Playgroud) 我正在阅读教程:https: //www.raywenderlich.com/148513/grand-central-dispatch-tutorial-swift-3-part-1
并且遇到了QoS类用户交互的定义.它在那里提到它应该在主线程上运行.那么,我的问题是那之间的区别是什么
DispatchQueue.global(qos: .userInteractive).async{}
Run Code Online (Sandbox Code Playgroud)
和
DispatchQueue.main.async{}
Run Code Online (Sandbox Code Playgroud)
谢谢!!
我UIAlertController将主线程呈现为:
class HelperMethodClass: NSObject {
class func showAlertMessage(message:String, viewController: UIViewController) {
let alertMessage = UIAlertController(title: "", message: message, preferredStyle: .alert)
let cancelAction = UIAlertAction(title: "Ok", style: .cancel)
alertMessage.addAction(cancelAction)
DispatchQueue.main.async {
viewController.present(alertMessage, animated: true, completion: nil)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我从任何方面调用方法UIViewController:
HelperMethodClass.showAlertMessage(message: "Any Message", viewController: self)
Run Code Online (Sandbox Code Playgroud)
我正确地得到了输出.
但在控制台中,我收到以下消息:
[Assert]在非主线程上无法使用asCopy = NO调用.
我在这里做错了什么,或者我可以忽略这个消息?
编辑
感谢@NicolasMiari:
添加以下代码不会显示任何消息:
DispatchQueue.main.async {
HelperMethodClass.showAlertMessage(message: "Any Message", viewController: self)
}
Run Code Online (Sandbox Code Playgroud)
之前它在控制台中显示消息的原因是什么?
如何使用DispatchQueue该类为 iOS 替换以下 Swift 代码?这是旧的 Swift 3 代码,最新的 Xcode 不会转换为 Swift 5。
dispatch_async(dispatch_get_main_queue()) { () -> Void in
// code
}
Run Code Online (Sandbox Code Playgroud)
它给了我一个错误,说
'dispatch_get_main_queue()' 的歧义使用
为dispatch_get_main_queue()。
以下答案似乎是正确答案,我想使用它,但有人可以告诉我这是正确的吗?迅捷版
它说使用以下代码:
DispatchQueue.global(qos: .background).async {
// Background Thread
DispatchQueue.main.async {
// Run UI Updates
}
}
Run Code Online (Sandbox Code Playgroud)
除了使用之外DispatchQueue,我还有什么其他选择可以解决这个错误?
stackoverflow 上的大多数答案都暗示同步与异步行为与串行与并发队列概念差异非常相似。就像@Roope 的第一条评论中的链接一样
我开始认为串行和并发与DispatchQueue同步/异步有关如何在线程上执行操作。我对吗?
就像如果我们已经得到DQ.main.sync那么任务/操作闭包将以同步方式在此串行(主)队列上执行。而且,如果我DQ.main.async这样做,任务将在其他后台队列上异步获取,并且在完成后将返回主线程的控制权。而且,由于 main 是一个串行队列,因此在当前关闭任务完成执行之前,它不会让任何其他任务/操作进入执行状态/开始执行。
然后,
DQ.global().sync将在已分配其任务/操作的线程上同步执行任务,即,它将通过阻止该特定线程上的任何上下文切换来阻止该线程执行任何其他任务/操作。并且,由于 global 是一个并发队列,因此无论先前任务/操作的执行状态如何,它都会继续将其中存在的任务置于执行状态。
DQ.global().async将允许在已执行操作闭包的线程上进行上下文切换
这是对上述调度队列和同步与异步的正确解释吗?
grand-central-dispatch ios swift ios-multithreading dispatch-queue
据我了解,swift中有 3 种类型的 DispatchQueue:
每一个都可能工作(异步或同步)
第一个问题:
主队列是否只在UI 线程上工作而不在另一个线程上工作?如果答案是肯定的,如何DispatchQueue.Main.async不阻塞 UI 线程。如果答案为 No ,那么DispatchQueue.global只要DispatchQueue.Main.async在另一个线程中工作,使用有什么好处。
第二个问题:
DispatchQueue.global (async)和 DispatchQueue.global (sync)之间的区别是什么,只要这个队列并发工作 ,在哪里使用每个队列?
第三个问题:
什么是差异
multithreading asynchronous grand-central-dispatch swift dispatch-queue
我有一个 UDP 方法,它使用以下代码使用 DispatchQueue 等待回复:
DispatchQueue.global(qos: .userInitiated).async {
let server:UDPServer=UDPServer(address:"0.0.0.0", port:5005)
let (data,_,_) = server.recv(1024)
DispatchQueue.main.async {
...
}
}
Run Code Online (Sandbox Code Playgroud)
这非常有效,并启动了一个等待我的数据进来的过程。如果我们从未收到回复,让我夜不能寐的是会发生什么?server.recv 永远不会返回,所以我看不到这个过程将如何结束?有没有办法给它预定的运行时间?
有时我必须在主线程上做一些事情,建议将代码放在OperationQueue.main.addOperation。
其他时候,建议在其中编写代码DispatchQueue.main.async。
两者之间有什么区别?
(有一个类似的问题标题,但是内容不匹配。)
我用 DispatchQueue 做了简单的测试:
DispatchQueue.global(qos: .background).sync {
if Thread.isMainThread {
print("Main thread")
}
}
Run Code Online (Sandbox Code Playgroud)
它打印出来:
Main thread
Run Code Online (Sandbox Code Playgroud)
为什么这段代码在主线程上执行?它应该在后台线程上执行(它被添加到后台队列中),对吗?
首先的问题是,在核心角色中使用核心蓝牙将数据发送到蓝牙 LE 设备的最佳方式是什么。需要处理数据,如果它在 UI 线程上运行,则需要足够的时间在 UI 线程上引起问题。用户将在手机应用程序打开的情况下启动该过程,然后继续使用该应用程序或关闭该应用程序并期望数据继续发送到设备。
我发现了 2 种非常糟糕的方法,它们似乎有效
这似乎源于 iOS 线程/调度队列以及 iOS 蓝牙内部结构。
蓝牙 LE iOS 应用程序作为核心角色连接到蓝牙 LE 设备。CBCentralManager 是根据苹果文档初始化的。队列定义为:
用于调度中心角色事件的调度队列。如果值为 nil,则中央管理器使用主队列分派中央角色事件。
正如vladiulianbogdan 对 Swift 的回答所建议的:为蓝牙中央管理器选择队列,我们应该为 CBCentralManager 创建一个串行队列。这似乎是有道理的,有一段时间我一直在遵循这个建议。此外allprog评论斯威夫特CoreBluetooth:在一个单独的线程应该CentralManager运行 表明,主队列将暂停,但其他队列不会,这是我所看到的是相反的。
在为蓝牙使用串行队列时,最好使用与主线程不同的队列。有一个问题:回调:
-(void)peripheralIsReadyToSendWriteWithoutResponse:(CBPeripheral *)peripheral
{
[self sendNextBluetoothLePacket];
}
Run Code Online (Sandbox Code Playgroud)
停止被调用。还有另一种方法可以检查外设是否准备好发送更多数据,CBPeripheral 有一个成员变量 canSendWriteWithoutResponse,如果可以发送则返回 true。此变量也开始重新调整 false 并且永远不会回到 true。
我从Sandeep Bhandari找到了这条评论,它说当应用程序进入后台时,所有队列线程都会停止,除非它们是苹果提供的后台模式之一。Biniou 发现他能够通过在视图控制器而不是应用程序委托中初始化来解决他的核心蓝牙背景问题。这对我来说没有意义。
我的应用程序确实在其 info.plist 中选择了核心蓝牙背景模式,因此它应该是这些背景模式之一。我发现当我的应用程序进入后台时,应用程序确实会继续处理数据。我看到来自每 100 毫秒运行一次的轮询循环的日志消息。
如果我从这些轮询循环中触发蓝牙 LE 写入,我就可以继续发送数据。问题是我无法确定发送数据的安全速率,要么速度很慢,要么数据有时会丢失。
我不确定如何最好地处理这个问题。任何建议,将不胜感激。似乎无论我在后台做什么,我都无法确定发送数据是否安全。
我看到这条评论 …
grand-central-dispatch ios core-bluetooth ios-bluetooth dispatch-queue
dispatch-queue ×10
swift ×9
ios ×6
asynchronous ×2
ambiguous ×1
concurrency ×1
operation ×1
qos ×1
queue ×1
swift4.2 ×1