2017-06-27 29 views
2

私はディスパッチグループを使用してデータ文字列を取得しています。ここにコードがあり、私はなぜこのコードでUnbalanced call to dispatch_group_leave()が得られるのか分かりません。ループ用の複製でdispatch_group_leave()への不均衡な呼び出し

var queue = DispatchQueue(label: "extractStringQueue", attributes: .concurrent) 
queue.async { 
    let m_group = DispatchGroup() 
    let weeks = self.weekDataArray 

    for week in weeks { 
     for day in week.dayDataArray { 
      m_group.enter() 
      day.processStringData(dataName, completionHandler: { (data, response, error) in 
        if true { 
         // Process 
         m_group.leave()  
        } 
       }) 
     } 
    } 

    m_group.notify(queue: queue, execute: { 
    // CompletionHandler 
    }) 
} 

答えて

1

二つの可能な問題:

問題1:

processStringData機能は、したがって、複数のm_group.leave()コールが得られ何度もそのcompletionHandler以上を呼び出すことがあります。 m_group.leave()の数は、常にm_group.enter()に等しくなければなりません。あなたがm_group.leave()回以上試みると、このエラーが表示されます。

問題2:

m_group.enter() 
    day.processStringData(dataName, completionHandler: { (data, response, error) in 
    if true { 
     // Process 
     m_group.leave()  
    } 
}) 

あなたのコードはcompletionHandlerは、それが偽u'llを返した場合にグループを離れることはないので、グループを離れtrueを返した場合にのみ、と言います。これにより、完了ブロックがfalseを返して不必要にスレッドを永久にブロックしたとしても、m_group.notifyはトリガーされません。

何uはむしろやるべきことは

m_group.enter() 
    day.processStringData(dataName, completionHandler: { (data, response, error) in 
    if true { 
     // Process  
    } 
    m_group.leave() 
}) 

問題3:

はprocessStringDataが完了ブロックを実行する前にスレッドを変更していないことを確認します。メインスレッドに戻り、完了ブロックを実行するのが一般的な方法です。 dispatch_groupに異なるスレッドを使用して入力し、グループを完全に別のスレッドから離そうとすると、不均衡なコールが残ることにもなります。

+0

興味深い説明非常によく説明しますが、私はあなたの第3のポイントを得ることができませんでした。あなたが知っていると多くのことを説明することができますか? –

+0

@myc-alter:本当に確かではありません:)通常は、完了ブロックを実行する前にメインスレッドに切り替えるプラクティスは、関数パラメータとして渡されます。実際のネットワークコールはバックグラウンドスレッドで発生しますが、サーバの応答を返す前にalamofireと同様にAFNetworkingがこれらのサードパーティフレームワークで実行されます。彼らが行うことは、DispatchQueue.main.async {completion()}内のcompletion()コールを囲むことです。ディスパッチグループが内部でセマフォースイッチングスレッドを使用しているため、スレッドスイッチが発生します。これは –

+0

のように、入力および退出のコールが不均衡になる可能性があります。ちょうど推測 –

関連する問題