iph*_*aaw 6 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 永远不会返回,所以我看不到这个过程将如何结束?有没有办法给它预定的运行时间?
没有办法阻止或“杀死”aDispatchWorkItem或NSOperation从外部。有一种cancel()方法,但它只是将isCancelled项目或操作的属性设置为 true。这并没有阻止该项目本身的执行。Ans 由于recv正在阻塞,因此无法isCancelled在执行期间检查标志。这意味着不幸的是 Vadian 发布的答案不会做任何事情。
按照苹果的文档上NSOperation.cancel:
此方法不会强制您的操作代码停止。
这同样适用于NSOperationQueue.cancelAllOperations:
取消操作不会自动将它们从队列中删除或停止当前正在执行的操作。
您可能认为可以下降到使用原始NSThread. 但是,同样的原则也适用。您无法从外部确定性地杀死线程。
可能的解决方案:超时
我能想到的最佳解决方案是使用套接字的超时功能。我不知道UDPServer从哪里来,但也许它有一个内置的超时。
可能的解决方案:穷人的超时(发送数据包到本地主机)
您可以尝试的另一种选择是在经过一段时间后向自己发送一些 UDP 数据包。这样,recv会收到一些数据,然后继续执行。这可能被用作“穷人的超时”。
添加一个在特定超时间隔后触发的计时器
声明超时间隔常量和计时器属性
private let timeoutSeconds = 30
private var timer : DispatchSourceTimer?
Run Code Online (Sandbox Code Playgroud)
并编写两个函数来启动和停止计时器。
fileprivate func startDispatchTimer()
{
let interval : DispatchTime = .now() + .seconds(timeoutSeconds)
if timer == nil {
timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
timer!.schedule(deadline:interval)
timer!.setEventHandler {
// do something when the timer fires
self.timer = nil
}
timer!.resume()
}
}
fileprivate func stopDispatchTimer()
{
timer?.cancel()
timer = nil
}
Run Code Online (Sandbox Code Playgroud)
初始化服务器实例后启动计时器并在成功时停止。失败时在setEventHandler闭包中添加代码来处理超时,例如取消分配服务器实例。
| 归档时间: |
|
| 查看次数: |
7074 次 |
| 最近记录: |