【问题标题】:Waiting for a task to finish before moving on to next one等待一项任务完成,然后再继续下一项
【发布时间】:2017-03-27 15:43:03
【问题描述】:

我使用NMSSH 连接到服务器,然后从该服务器获取数据。但是,连接到服务器、执行命令和检索数据都需要时间来完成。以前,我使用sleep() 命令来允许程序暂停并让这些命令完成运行,但如果我没有指定确切的睡眠时间,数据可能无法完全完成下载(因为数据在大小很难确定正确的睡眠量)。因此,在做了一些研究之后,Dispatch Groups 和 Async 操作似乎是正确的方法。我按如下方式实现了这些:

let queue = DispatchQueue(label: "myqueue")
let group = DispatchGroup()    
let myfirstconnection: SSH = SSH()
myfirstconnection.hostname = "@hostname"
myfirstconnection.username = "user"
myfirstconnection.password = "password"

queue.async(group: group) {
    myfirstconnection.connectToServer()
    print("1")
}
group.wait()

queue.async(group: group) {
    myfirstconnection.performCommand()
    print("2")
}
group.wait()

queue.async(group: group) {
    myfirstconnection.retrieveData()
    print("3")
}
group.wait()

queue.async(group: group) {
    myfirstconnection.endSession()
    print("4")
}
group.wait()

但是,这似乎无法正常工作,因为所有命令仍同时运行。基本上我需要上面的每个块都运行,然后等到完成后再移动到下一个块。

【问题讨论】:

  • 为什么要先发送四个异步请求?如果您将这四个 myfirstconnection 调用包装在一个异步块中,它们将相对于彼此按顺序执行
  • 因为我进行的每个调用都需要时间单独运行,所以如果我一个接一个地调用它们,第一个在尝试执行命令之前将无法完成连接,从而导致错误。跨度>

标签: ios swift


【解决方案1】:

NMSSH 框架遵循(非常!)常见的委托模式(例如,UIText​Field​ 视图及其来自UIKit 框架的UIText​Field​Delegate 协议;等等)。因此,所有网络操作都在后台运行,并在完成后触发相应的协议方法。

您应该实现NMSSHSessionDelegateNMSSHChannelDelegate 协议以收到此类事件的通知。请记住,这样做时您的代码结构看起来会非常不同。

希望有帮助 ;-)

【讨论】:

  • 如果您指的是 - (void)channel:(NMSSHChannel *)channel didReadData:(NSString *)message 委托调用,我以前使用过它,但我唯一遇到的问题是它甚至可以识别输入的执行命令(例如 cd home),我只想要调用执行后返回的数据,所以我一直在我的retrieveData 方法中使用命令[self.session.channel lastResponse];
  • @SpartanEngr1297 这看起来像是 API 设计中的一个小问题。无论如何,如果你真的需要控制执行步骤——我认为你会这样做! — 你应该再试一次这些协议 ;-)
【解决方案2】:

好的,首先使用sleep() 根本不起作用,因为你想如何估计下载某些东西所需的时间,有些连接可能很快,有些可能很慢。 根据我对您的问题的理解,您想要执行一些任务,然后对数据做一些事情,然后继续下一个任务,直到它们完成。一次一个项目。 对于这种情况,我有一个解决方案,但我不确定这是否是最好的方法,但它有效。

        let serialQueue = DispatchQueue(label: "serialQueueWork" )
        let semaphore = DispatchSemaphore(value: 1)

        let task1 = DispatchWorkItem {
            semaphore.wait()
            print("1 started.")
            for _ in 0...5{
                print("♥️")
            }
        }

        let task2 = DispatchWorkItem  {
            semaphore.wait()
            print("2 started.")
            for _ in 0...5{
                print("♣️")
            }
        }

        task1.notify(queue: DispatchQueue.main) {
            print("1 is finished.")
            semaphore.signal()
        }

        task2.notify(queue: DispatchQueue.main) {
            print("2 is finished")
            semaphore.signal()
        }

        serialQueue.async(execute: task1 )
        serialQueue.async(execute: task2 )


// console result

1 开始。 ♥️ ♥️ ♥️ ♥️ ♥️ ♥️ 1完结了。 2 开始。 ♣️ ♣️ ♣️ ♣️ ♣️ ♣️ 2完结了

使用semaphore,您可以控制队列何时可以继续工作。 使用DispatchWorkItem 当工作完成时你会收到通知并让队列继续。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-31
    相关资源
    最近更新 更多