繁体   English   中英

分派到主线程时返回值

[英]Returning value while dispatching to the main thread

我有一个功能func getValue() -> Bool从后台线程调用的func getValue() -> Bool 这是有意的,也是必需的。 现在, getValue()需要在主线程上执行某些操作,在这种情况下,它需要访问UIApplication.shared.canOpenURL ,该必须在主队列上运行。

这是我当前的功能:

func getValue() -> Bool {
    guard let url = URL(string: "someurl") else { return false }
    return UIApplication.shared.canOpenURL(url)
}

我如何才能将该函数转换为线程安全的函数,即确保该函数始终在主线程上运行,而无需

  • 从主线程调用函数开始
  • 重构函数以在闭包中返回值

我已经试过了:

// This causes a deadlock, see https://stackoverflow.com/a/42484670/1531270
func getValue() -> Bool {
    var flag = false

    let group = DispatchGroup()
    group.enter()
    DispatchQueue.main.async {
        if let url = URL(string: "someurl"), UIApplication.shared.canOpenURL(url) {
            flag = true
        }
        group.leave()
    }
    group.wait()

    return flag
}

和这个:

// This crashes with EXC_BREAKPOINT (SIGTRAP) dispatch_sync called on queue already owned by current thread
func getValue() -> Bool {
    return DispatchQueue.main.sync {
        guard let url = URL(string: "someurl") else { return false }
        return UIApplication.shared.canOpenURL(url)
    }
}

但它们都不起作用。 有任何想法吗?

您正在寻找信号量-试试这个:

DispatchQueue.global(qos: .background).async {
    var value: Bool? = nil
    let semaphore = DispatchSemaphore(value: 0)
    DispatchQueue.main.async {
        let alert = UIAlertController(title: "Choose one", message: "Take your time, I'll wait", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "true", style: .default, handler: { _ in
            value = true
            semaphore.signal()
        }))
        alert.addAction(UIAlertAction(title: "false", style: .default, handler: { _ in
            value = false
            semaphore.signal()
        }))
        self.present(alert, animated: true, completion: nil)
    }
    semaphore.wait()
    print("Choice: \(value!)")
}

或使用上面的示例:

func getValue() -> Bool {
    var flag = false
    let semaphore = DispatchSemaphore(value: 0)

    DispatchQueue.main.async {
        if let url = URL(string: "someurl"), UIApplication.shared.canOpenURL(url) {
            flag = true
            semaphore.signal()
        }
    }
    semaphore.wait()
    return flag
}

对于您的第二个示例,我无法重现任何问题。 您没有显示如何调用getValue ,所以我做了一些事情:

func getValue() -> Bool {
   return DispatchQueue.main.sync {
        guard let url = URL(string: "testing://testing") else { return false }
        return UIApplication.shared.canOpenURL(url)
   }
}
override func viewDidLoad() {
    super.viewDidLoad()
    DispatchQueue.global(qos:.background).async {
        let ok = self.getValue()
        print(ok) // false, the right answer
    }
}

没有“崩溃”,所以我就去解决。 当我使用的方案testing:我得到的false ,当我改变testing:https:我回到true ,所以明确方法调用工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM