6

我有一个 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 永远不会返回,所以我看不到该过程将如何结束?有没有办法给它预定的运行时间?

4

3 回答 3

7

没有办法阻止或“杀死” a DispatchWorkItemorNSOperation从外部。有一种cancel()方法,但它只是将isCancelled项目或操作的属性设置为 true。这不会停止项目本身的执行。Ans 因为recv是阻塞的,所以在执行期间没有办法检查isCancelled标志。这意味着 Vadian 发布的答案很遗憾不会做任何事情。

根据Apple文档NSOperation.cancel

此方法不会强制您的操作代码停止。

这同样适用于NSOperationQueue.cancelAllOperations

取消操作不会自动将它们从队列中删除或停止当前正在执行的操作。

您可能认为可以直接使用 raw NSThread。然而,同样的原则也适用于他。您不能确定性地从外部杀死线程。

可能的解决方案:超时

我能想到的最佳解决方案是使用套接字的超时功能。我不知道UDPServer从哪里来,但也许它有一个内置的超时。

可能的解决方案:穷人的超时(将数据包发送到本地主机)

您可以尝试的另一种选择是在经过一定时间后向自己发送一些 UDP 数据包。这样,recv将收到一些数据,并继续执行。这可能被用作“穷人的超时”。

于 2019-01-26T08:53:15.273 回答
4

添加一个在特定超时间隔后触发的计时器

为超时间隔声明一个常量,为计时器声明一个属性

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闭包中添加代码以处理超时,例如解除分配服务器实例。

于 2019-01-22T08:17:22.317 回答
0

where 不应该是 UDPServer 不会返回的任何情况。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 {
            ...
        }
    }
于 2019-01-27T03:37:59.253 回答