我有一个后台线程需要一些用户输入。由于不建议从后台线程调用NSAlert窗口,我喜欢在主线程中执行此操作。但是,如何让后台线程等到NSAlert窗口关闭?
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// some background task
dispatch_async(dispatch_get_main_queue()) {
// UI task asking for user input:
let alert = NSAlert()
alert.messageText = "Some text"
alert.informativeText = "Some information"
alert.addButtonWithTitle("Yes")
alert.addButtonWithTitle("No")
result = alert.runModal()
}
// some background task, treating user input (Yes/No)
}
答案 0 :(得分:3)
runModal
方法是同步的。如果您想等待它完成,而不是使用dispatch_async
异步调度到主队列,您可以通过与dispatch_sync
同步调度来轻松实现您的要求,例如:
let queue = dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0)
dispatch_async(queue) {
// some background task
var result: NSModalResponse!
dispatch_sync(dispatch_get_main_queue()) { // note, `dispatch_sync`
// UI task asking for user input:
let alert = NSAlert()
...
result = alert.runModal()
}
// some background task, treating user input (Yes/No)
}
一个更微妙的问题在于同步性runModal
。这将阻止主线程。这通常不是一个好主意。它可能会干扰您的应用可能需要主线程执行的其他任务(定时器,动画,使用主队列的网络操作等)。
因此,您可以考虑使用完成处理程序向后台队列调度其他后台处理,而不是同步runModal
,而不是同步NSAlert
,例如:< / p>
beginSheetModalForWindow
这可以达到你想要的效果(当模态被解除时触发额外的后台任务),但具有不阻塞主线程的优点。
答案 1 :(得分:-2)
您可以使用信号量。
dispatch_async(dispatch_get_global_queue(priority, 0)) {
// some background task
//Create a semaphore with count = 0
let semaphore = dispatch_semaphore_create(0)
dispatch_async(dispatch_get_main_queue()) {
// UI task asking for user input:
let alert = NSAlert()
alert.messageText = "Some text"
alert.informativeText = "Some information"
alert.addButtonWithTitle("Yes")
alert.addButtonWithTitle("No")
result = alert.runModal()
//Signal semaphore
dispatch_semaphore_signal(semaphore)
}
//Wait for semaphore
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
// some background task, treating user input (Yes/No)
}
你不应该在主线程中“等待” 。但背景线程是其他事情。