我有一个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永远不会返回,所以我看不到进程将如何结束?有没有一种方法可以给它预定的运行时间?
答案 0 :(得分:3)
添加一个在特定的超时间隔后触发的计时器
为超时间隔声明常量,并为计时器设置属性
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
闭包中添加代码以处理超时,例如取消分配服务器实例。
答案 1 :(得分:3)
无法从外部停止或“杀死” DispatchWorkItem
或NSOperation
。有一个cancel()
方法,但是仅将项目或操作的isCancelled
属性设置为true。这不会不停止项目本身的执行。由于recv
被阻止,因此无法在执行期间检查isCancelled
标志。不幸的是,这意味着Vadian发布的答案将无济于事。
根据NSOperation.cancel
上的Apple docs:
此方法不会强制您的操作代码停止。
The same用于NSOperationQueue.cancelAllOperations
:
取消操作不会自动将其从队列中删除或停止当前正在执行的操作。
您可能认为可以使用原始NSThread
。但是,相同的原则也适用。您不能确定地从外部杀死线程。
可能的解决方案:超时
我能想到的最好的解决方案是使用套接字的超时功能。我不知道UDPServer
的来源,但也许它具有内置超时功能。
可能的解决方案:可怜的人超时(将数据包发送到本地主机)
您可以尝试的另一种选择是在经过一定时间后向自己发送一些UDP数据包。这样,recv
将接收一些数据,并继续执行。这可能被用作“穷人的超时”。
答案 2 :(得分:0)
在任何情况下UDPServer都不会返回。 UDPServer应该等待多长时间应该有超时限制。例如,考虑以下情况:
X=features
y=labels
for train_index, test_index in sss.split(X, y):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]