2017-06-09 8 views
0

私は写真のオブジェクトを認識するアルゴリズムを持っています。主な問題は、スレッドセーフではないことです。新しい構成を設定したとき、または処理差異がまだ残っているときに新しいイメージの処理を開始するとき、アルゴリズムの動作は未定義であり、クラッシュする可能性があります。私のコードと私の実装はうまくいかなかった。スレッドセーフな処理

// 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) } 
     } 
} 

私は、背景にこの計算を派遣すると間違って何かをやっていると思うが、私はこれを行うには正しい解決策を見つけることができません。

答えて

0

私が提供したコードは、あなたの問題に明確な答えを得るには不十分だと思います。あなたがなど、あなたのクラッシュのいくつかのコールスタックを掲示している場合には参考になる

まず考えている:彼らは実行するため

  • たぶんオブザーバーは、任意のスレッド(グローバルキュー)から呼び出されることができませんいくつかのUIアップデートなどがあります。この場合、didProcessをメインキューから呼び出すことができます。
  • から呼び出されている間に一部のオブザーバーが自分自身を削除する、つまりforEach呼び出しが変更されたコレクションで機能するという問題があるかもしれません。この場合、オブザーバ配列を横断する前にコピーする必要があります。
  • あなたはまた、(深い)に試みることができるが、これは少し:-)

    を助けて「より」スレッドセーフ

希望にするために、アルゴリズムのクラスをコピーします

関連する問題