线程安全处理

时间:2017-06-09 06:59:09

标签: ios swift multithreading grand-central-dispatch

我有一种识别照片中对象的算法。主要问题是它不是线程安全的,所以e.x.当您设置新的配置或当您仍处理差异时开始处理新图像时,算法的行为是未定义的并且可能会崩溃。下面我把我的代码和我的实现放得不行。

// config struct
public struct Config {} 

// reslut of the algorithm
public struct Product {}  

// algorith class
public class Recognizer { 
   func apply(config: Config)
   func process(frame: UIImage) -> Product {
       let prodcut = Product()
       return prodcut
   } 
}

// protocol for an object interested in the result of the Recognizer
protocol Observer: class {
    func didProcess(frame: UIImage, prodcut: Prodcut) 
}

// protocol that wraps Recognizer class
protocol RecognizerService {
    func add(observer: Observer)
    func remove(observer: Observer)
    var recognitionConfig: Config { get set }
    func process(frame: UIImage)
}

现在看起来如何。

let recognizerQueue: DispatchQueue = DispatchQueue.global(qos: .background)

class HumanFaceRecognizer: RecognizerService {
      var recognitionConfig: Config
      var observers: [Observer]
      let algorythm: Recognizer
      private var recognizerQueue: DispatchQueue

      init(recognitionConfig: Config,
           observers: [Observer] = [],
           recognizerQueue: DispatchQueue,
           algorythm: Recognizer) {
           self.recognitionConfig = recognitionConfig
           self.observers = observers
           self.recognizerQueue = recognizerQueue
           self.algorythm = algorythm
      }

      func add(observer: Observer) {
          observers.append(observer)
      } 

      func remove(observer: Observer) {
          observers.remove(observer)
      }

      func process(frame: UIImage) {
          recognizerQueue.async { [weak self, currentFrame = frame, currentConfig = recognitionConfig] in
          self?.algorythm.process(frame: currentFrame)
          observers.forEach { $0.didProcess(frame: currentFrame, result: currentConfig) }
      }
}

我认为将这个计算调度到后台我做错了,但我找不到正确的解决方案来做到这一点。

1 个答案:

答案 0 :(得分:0)

我认为您提供的代码不足以明确您的问题。如果您发布了一些崩溃等的调用堆栈,将会很有帮助。

首先想到的是:

  • 可能观察者无法从任意线程(全局队列)调用,因为他们执行一些UI更新等。在这种情况下,您可以从主队列中调用didProcess
  • 可能有一些观察者在HumanFaceRecognizer中调用didProcess时将其自身从forEach中移除,即{{1}}调用适用于已修改的集合。在这种情况下,您应该在遍历它之前复制观察者数组。
  • 您还可以尝试(深入)复制算法类,使其“更”线程安全

希望这有点帮助: - )