Search code examples
iosmultithreadinguiprogressview

Can't perform action in background and update progressView in mainThread


I've this method :

func stepThree() {
    operation = "prDatas"
    let entries = self.data.componentsSeparatedByString("|***|")
    total = entries.count
    for entry in entries {
        ++current
        dispatch_sync(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {
            self.registerDB(entry)
        })
    }
    status.setProgress(Float(current/total), animated: true)
    finishAll()
}

I want to perform registerDB function and update my progressBar when complete. I tested several way but never succeed


EDIT 1

Implementing @Russell proposition, work perfectly, but calculating value inside dispatch_async block always result to 0

Is there an issue about operations and multithread ?

method :

func stepThree() {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
        var current = 0
        var total = 0
        self.operation = "prDatas"
        let entries = self.data.componentsSeparatedByString("|***|")
        total = entries.count
        for entry in entries {
            ++current
            self.registerDB(entry)
            dispatch_async(dispatch_get_main_queue(), {
                print("value of 'current' is :" + String(current))
                print("value of 'total' is :" + String(total))
                print("Result is : " + String(Float(current/total)))
                self.updateV(Float(current/total))
            })
        }
    })
}

Console output :

value of 'current' is :71
value of 'total' is :1328
Result is : 0.0

Solution

  • Your code will update the status bar immediately - so the job will not have finished.

    You need to move the update so that it actually follows the registerDB function, and then you have to make the call on the main thread. Here's an example - using dummy functions instead of your function calls, so that I can ensure it works as expected

    func stepThree()
    {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), {
            let total = 5 // test data for demo
            for entry in 0...total
            {
                // dummy function - just pause
                sleep(1)
                //self.registerDB(entry)
    
                // make UI update on main queue
                dispatch_async(dispatch_get_main_queue(),
                {
                    self.setProgress(Float(entry)/Float(total))
                })
            }
        })
    }
    
    func setProgress(progress : Float)
    {
        progressView.progress = progress
        lblProgress.text = String(format: "%0.2f", progress)
    }