如果执行操作太长,则退出无限循环

时间:2016-10-21 20:56:27

标签: ios swift multithreading

我有一个函数发送命令,然后在无限循环中从USB设备读取数据并完成回调:

func dump(success: (() -> Void)? = nil, failure: (()->Void)? = nil) {
    HIDDevice.sharedInstance.sendCommad(command: "dump")
    while true {
        for data in HIDDevice.sharedInstance.readBuf {
            if data == "dumpcomplete":
               success?()
               return
        }
    }
}

我需要检查这个while循环是否有效> 1秒并且没有成功,然后调用failure闭包并停止循环。

我尝试在循环之前使用它,但它没有帮助。线程块循环。

func setTimeout(delay:TimeInterval, block:@escaping ()->Void) -> Timer {
    return Timer.scheduledTimer(timeInterval: delay, target: BlockOperation(block: block), selector: #selector(Operation.main), userInfo: nil, repeats: false)
}

let handle = setTimeout(1, block: { () -> Void in
    failure()?
    return
})

2 个答案:

答案 0 :(得分:4)

虽然我不认为这样的"繁忙的循环"是一个好主意,我对[{1}}一无所知,所以我无法提供这种循环的替代方案。所以这个答案只解决了1秒后如何退出HIDDevice循环的直接问题。

一种可能的解决方案是计算时间间隔并每次检查:

while

这将计算未来的时间间隔,并根据该未来值检查当前时间。一旦该时间过去,func dump(success: (() -> Void)? = nil, failure: (()->Void)? = nil) { HIDDevice.sharedInstance.sendCommad(command: "dump") let deadline = Date.timeIntervalSinceReferenceDate + 1 // add one second from now while Date.timeIntervalSinceReferenceDate < deadline { for data in HIDDevice.sharedInstance.readBuf { if data == "dumpcomplete": success?() return } } } 循环将退出。

答案 1 :(得分:2)

使用Grand Central Dispatch

rmaddyy的答案有效,但当前时间的不断抽样变得非常昂贵。

作为替代方法,我建议你多线程。这是一个为您执行循环的函数,并在超时后停止循环。如果循环成功结束或超时,它还会返回void List<T>::insert_at_front(const T &value) { ListNode<T> *new_node_ptr = get_new_node(value); ... } ListNode<T> *List<T>::get_new_node(const T &value) { return new ListNode<T>(value); } 通知您。

DispatchTimeoutResult

以下是您案例的示例实现:

import Dispatch

func BusyLoop(timeout: DispatchTimeInterval,
              qos: DispatchQoS = .background,
              _ block: @escaping @convention(block) ( () -> Void ) -> Void) -> DispatchTimeoutResult {
    var shouldLoop = true;
    let BreakLoop = { shouldLoop = false } //callback to stop looping

    let item = DispatchWorkItem() {
        while shouldLoop {
            block(BreakLoop)
        }
    }

    let queue = DispatchQueue(label: "Busy Loop", qos: qos) //TODO: Name me
    queue.async(execute: item)

    let state = item.wait(timeout: .now() + timeout)
    if state == .timedOut {
        shouldLoop = false
    }

    return state
}

var i = 0

BusyLoop(timeout: .seconds(1)) { BreakLoop in
    //treat this as the loop body
    print(i)
    i += 1

    if i == 1000 { BreakLoop() } //treat this as "break"
    // "return" acts as "continue"
}


switch timeoutResult {
case .success: print("Finished on time")
case .timedOut: print("Timed out")
}