快速取消DispatchQueue流程

时间:2019-01-17 15:22:51

标签: 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 {
       ...
    }
}

这非常有效,并且启动了一个等待我的数据输入的过程。如果没有得到答复,那让我彻夜难眠是怎么回事? server.recv永远不会返回,所以我看不到进程将如何结束?有没有一种方法可以给它预定的运行时间?

3 个答案:

答案 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)

无法从外部停止或“杀死” DispatchWorkItemNSOperation。有一个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]