如何防止命令行工具在异步操作完成之前退出
How to prevent a Command Line Tool from exiting before asynchronous operation completes
在 swift 2 命令行工具 (main.swift) 中,我有以下内容:
import Foundation
print("yay")
var request = HTTPTask()
request.GET("http://www.whosebug.com", parameters: nil, completionHandler: {(response: HTTPResponse) in
if let err = response.error {
print("error: \(err.localizedDescription)")
return //also notify app of failure as needed
}
if let data = response.responseObject as? NSData {
let str = NSString(data: data, encoding: NSUTF8StringEncoding)
print("response: \(str)") //prints the HTML of the page
}
})
控制台显示 'yay' 然后退出(程序结束,退出代码:0),似乎没有等待请求完成。我该如何防止这种情况发生?
代码正在使用 swiftHTTP
我想我可能需要一个 NSRunLoop 但没有 swift 示例
在文件末尾添加 RunLoop.main.run()
是一种选择。有关使用信号量的另一种方法的更多信息
如果您的需求不是需要"production level"代码的东西,而是一些快速实验或一段代码的试用, 你可以这样做:
SWIFT 3
//put at the end of your main file
RunLoop.main.run(until: Date(timeIntervalSinceNow: 15)) //will run your app for 15 seconds only
更多信息:
请注意您不应依赖架构中的固定执行时间。
你可以在main的最后调用dispatchMain()
。它运行 GCD 主队列调度程序,从不运行 returns,因此它将阻止主线程退出。然后您只需要在准备就绪时显式调用 exit()
退出应用程序(否则命令行应用程序将挂起)。
import Foundation
let url = URL(string:"http://www.whosebug.com")!
let dataTask = URLSession.shared.dataTask(with:url) { (data, response, error) in
// handle the network response
print("data=\(data)")
print("response=\(response)")
print("error=\(error)")
// explicitly exit the program after response is handled
exit(EXIT_SUCCESS)
}
dataTask.resume()
// Run GCD main dispatcher, this function never returns, call exit() elsewhere to quit the program or it will hang
dispatchMain()
不要依赖时间..你应该试试这个
let sema = DispatchSemaphore(value: 0)
let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/4/4d/Cat_November_2010-1a.jpg")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
print("after image is downloaded")
// signals the process to continue
sema.signal()
}
task.resume()
// sets the process to wait
sema.wait()
我意识到这是一个老问题,但这是我最终得出的解决方案。使用 DispatchGroup.
let dispatchGroup = DispatchGroup()
for someItem in items {
dispatchGroup.enter()
doSomeAsyncWork(item: someItem) {
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: DispatchQueue.main) {
exit(EXIT_SUCCESS)
}
dispatchMain()
Swift 4: RunLoop.main.run()
在你的文件末尾
// Step 1: Add isDone global flag
var isDone = false
// Step 2: Set isDone to true in callback
request.GET(...) {
...
isDone = true
}
// Step 3: Add waiting block at the end of code
while(!isDone) {
// run your code for 0.1 second
RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
}
在 swift 2 命令行工具 (main.swift) 中,我有以下内容:
import Foundation
print("yay")
var request = HTTPTask()
request.GET("http://www.whosebug.com", parameters: nil, completionHandler: {(response: HTTPResponse) in
if let err = response.error {
print("error: \(err.localizedDescription)")
return //also notify app of failure as needed
}
if let data = response.responseObject as? NSData {
let str = NSString(data: data, encoding: NSUTF8StringEncoding)
print("response: \(str)") //prints the HTML of the page
}
})
控制台显示 'yay' 然后退出(程序结束,退出代码:0),似乎没有等待请求完成。我该如何防止这种情况发生?
代码正在使用 swiftHTTP
我想我可能需要一个 NSRunLoop 但没有 swift 示例
在文件末尾添加 RunLoop.main.run()
是一种选择。有关使用信号量的另一种方法的更多信息
如果您的需求不是需要"production level"代码的东西,而是一些快速实验或一段代码的试用, 你可以这样做:
SWIFT 3
//put at the end of your main file
RunLoop.main.run(until: Date(timeIntervalSinceNow: 15)) //will run your app for 15 seconds only
更多信息:
请注意您不应依赖架构中的固定执行时间。
你可以在main的最后调用dispatchMain()
。它运行 GCD 主队列调度程序,从不运行 returns,因此它将阻止主线程退出。然后您只需要在准备就绪时显式调用 exit()
退出应用程序(否则命令行应用程序将挂起)。
import Foundation
let url = URL(string:"http://www.whosebug.com")!
let dataTask = URLSession.shared.dataTask(with:url) { (data, response, error) in
// handle the network response
print("data=\(data)")
print("response=\(response)")
print("error=\(error)")
// explicitly exit the program after response is handled
exit(EXIT_SUCCESS)
}
dataTask.resume()
// Run GCD main dispatcher, this function never returns, call exit() elsewhere to quit the program or it will hang
dispatchMain()
不要依赖时间..你应该试试这个
let sema = DispatchSemaphore(value: 0)
let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/4/4d/Cat_November_2010-1a.jpg")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
print("after image is downloaded")
// signals the process to continue
sema.signal()
}
task.resume()
// sets the process to wait
sema.wait()
我意识到这是一个老问题,但这是我最终得出的解决方案。使用 DispatchGroup.
let dispatchGroup = DispatchGroup()
for someItem in items {
dispatchGroup.enter()
doSomeAsyncWork(item: someItem) {
dispatchGroup.leave()
}
}
dispatchGroup.notify(queue: DispatchQueue.main) {
exit(EXIT_SUCCESS)
}
dispatchMain()
Swift 4: RunLoop.main.run()
在你的文件末尾
// Step 1: Add isDone global flag
var isDone = false
// Step 2: Set isDone to true in callback
request.GET(...) {
...
isDone = true
}
// Step 3: Add waiting block at the end of code
while(!isDone) {
// run your code for 0.1 second
RunLoop.main.run(until: Date(timeIntervalSinceNow: 0.1))
}