Swift 取消 DispatchQueue 进程
Swift Cancel DispatchQueue Process
我有一个 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 {
...
}
}
这非常有效,并启动了一个等待我的数据进入的过程。让我彻夜难眠的是如果我们没有得到回复会发生什么? server.recv 从来没有 returns 所以我看不出这个过程将如何结束?有没有办法给它预定的时间 运行 for?
添加一个在特定超时间隔后触发的计时器
为超时间隔声明一个常量,为定时器声明一个属性
private let timeoutSeconds = 30
private var timer : DispatchSourceTimer?
并编写两个函数来启动和停止定时器。
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
}
初始化服务器实例后启动计时器,并在成功时停止。失败时在 setEventHandler
闭包中添加代码以处理超时,例如解除分配服务器实例。
没有办法从外面停止或"kill"一个DispatchWorkItem
或NSOperation
。有一个 cancel()
方法,但它只是将项目或操作的 isCancelled
属性 设置为 true。这 不会 停止项目本身的执行。 Ans 由于 recv
正在阻塞,因此无法在执行期间检查 isCancelled
标志。这意味着 Vadian 发布的答案很遗憾不会做任何事情。
根据 NSOperation.cancel
上的 Apple docs:
This method does not force your operation code to stop.
The same 对应 NSOperationQueue.cancelAllOperations
:
Canceling the operations does not automatically remove them from the queue or stop those that are currently executing.
您可能认为可以使用原始 NSThread
。然而,同样的原则适用于他。您不能确定性地从外部杀死线程。
可能的解决方案:超时
我能想到的最佳解决方案是使用套接字的超时功能。我不知道 UDPServer
的来源,但也许它有一个内置超时。
可能的解决方案:穷人超时(发送数据包到本地主机)
您可以尝试的另一种选择是在经过一定时间后向您自己发送一些 UDP 数据包。这样,recv
会收到一些数据,然后继续执行。这可能用作 "poor man's timeout".
不应该是 UDPServer 不会 return 的任何情况。 UDPServer 应该等待多长时间应该有超时限制。例如考虑以下情况:
DispatchQueue.global(qos: .background).async {
let server = UDPServer(address:"0.0.0.0", port:5005)
switch server.recv(1024) {
case .success:
print("Server received message from client.")
case .failure(let error):
print("Server failed to received message from client: \(error)")
}
server.close()
DispatchQueue.main.async {
...
}
}
我有一个 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 {
...
}
}
这非常有效,并启动了一个等待我的数据进入的过程。让我彻夜难眠的是如果我们没有得到回复会发生什么? server.recv 从来没有 returns 所以我看不出这个过程将如何结束?有没有办法给它预定的时间 运行 for?
添加一个在特定超时间隔后触发的计时器
为超时间隔声明一个常量,为定时器声明一个属性
private let timeoutSeconds = 30
private var timer : DispatchSourceTimer?
并编写两个函数来启动和停止定时器。
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
}
初始化服务器实例后启动计时器,并在成功时停止。失败时在 setEventHandler
闭包中添加代码以处理超时,例如解除分配服务器实例。
没有办法从外面停止或"kill"一个DispatchWorkItem
或NSOperation
。有一个 cancel()
方法,但它只是将项目或操作的 isCancelled
属性 设置为 true。这 不会 停止项目本身的执行。 Ans 由于 recv
正在阻塞,因此无法在执行期间检查 isCancelled
标志。这意味着 Vadian 发布的答案很遗憾不会做任何事情。
根据 NSOperation.cancel
上的 Apple docs:
This method does not force your operation code to stop.
The same 对应 NSOperationQueue.cancelAllOperations
:
Canceling the operations does not automatically remove them from the queue or stop those that are currently executing.
您可能认为可以使用原始 NSThread
。然而,同样的原则适用于他。您不能确定性地从外部杀死线程。
可能的解决方案:超时
我能想到的最佳解决方案是使用套接字的超时功能。我不知道 UDPServer
的来源,但也许它有一个内置超时。
可能的解决方案:穷人超时(发送数据包到本地主机)
您可以尝试的另一种选择是在经过一定时间后向您自己发送一些 UDP 数据包。这样,recv
会收到一些数据,然后继续执行。这可能用作 "poor man's timeout".
不应该是 UDPServer 不会 return 的任何情况。 UDPServer 应该等待多长时间应该有超时限制。例如考虑以下情况:
DispatchQueue.global(qos: .background).async {
let server = UDPServer(address:"0.0.0.0", port:5005)
switch server.recv(1024) {
case .success:
print("Server received message from client.")
case .failure(let error):
print("Server failed to received message from client: \(error)")
}
server.close()
DispatchQueue.main.async {
...
}
}